#include "astyle.h"
#include <algorithm>
#include <fstream>

namespace astyle {
  ASFormatter::ASFormatter() {
    sourceIterator = nullptr;
    enhancer = new ASEnhancer;
    preBraceHeaderStack = nullptr;
    braceTypeStack = nullptr;
    parenStack = nullptr;
    structStack = nullptr;
    questionMarkStack = nullptr;
    lineCommentNoIndent = false;
    formattingStyle = STYLE_NONE;
    braceFormatMode = NONE_MODE;
    pointerAlignment = PTR_ALIGN_NONE;
    referenceAlignment = REF_SAME_AS_PTR;
    objCColonPadMode = COLON_PAD_NO_CHANGE;
    maxCodeLength = string::npos;
    shouldPadCommas = false;
    shouldPadOperators = false;
    shouldPadParensOutside = false;
    shouldPadFirstParen = false;
    shouldPadParensInside = false;
    shouldPadHeader = false;
    shouldStripCommentPrefix = false;
    shouldUnPadParens = false;
    attachClosingBraceMode = false;
    shouldBreakOneLineBlocks = true;
    shouldBreakOneLineHeaders = false;
    shouldBreakOneLineStatements = true;
    shouldConvertTabs = false;
    shouldIndentCol1Comments = false;
    shouldIndentPreprocBlock = false;
    shouldCloseTemplates = false;
    shouldAttachExternC = false;
    shouldAttachNamespace = false;
    shouldAttachClass = false;
    shouldAttachClosingWhile = false;
    shouldAttachInline = false;
    shouldBreakBlocks = false;
    shouldBreakClosingHeaderBlocks = false;
    shouldBreakClosingHeaderBraces = false;
    shouldDeleteEmptyLines = false;
    shouldBreakElseIfs = false;
    shouldBreakLineAfterLogical = false;
    shouldAddBraces = false;
    shouldAddOneLineBraces = false;
    shouldRemoveBraces = false;
    shouldPadMethodColon = false;
    shouldPadMethodPrefix = false;
    shouldUnPadMethodPrefix = false;
    shouldPadReturnType = false;
    shouldUnPadReturnType = false;
    shouldPadParamType = false;
    shouldUnPadParamType = false;
    formatterFileType = 9;
    headers = new vector<const string*>;
    nonParenHeaders = new vector<const string*>;
    preDefinitionHeaders = new vector<const string*>;
    preCommandHeaders = new vector<const string*>;
    operators = new vector<const string*>;
    assignmentOperators = new vector<const string*>;
    castOperators = new vector<const string*>;
    indentableMacros = new vector<const pair<const string, const string>* >;
  }


  ASFormatter::~ASFormatter() {
    deleteContainer( preBraceHeaderStack );
    deleteContainer( braceTypeStack );
    deleteContainer( parenStack );
    deleteContainer( structStack );
    deleteContainer( questionMarkStack );
    formatterFileType = 9;
    delete headers;
    delete nonParenHeaders;
    delete preDefinitionHeaders;
    delete preCommandHeaders;
    delete operators;
    delete assignmentOperators;
    delete castOperators;
    delete indentableMacros;
    ASBeautifier::deleteBeautifierVectors();
    delete enhancer;
  }


  void ASFormatter::init( ASSourceIterator* si ) {
    buildLanguageVectors();
    fixOptionVariableConflicts();
    ASBeautifier::init( si );
    sourceIterator = si;
    enhancer->init( getFileType(),
                    getIndentLength(),
                    getTabLength(),
                    getIndentString() == "\t",
                    getForceTabIndentation(),
                    getNamespaceIndent(),
                    getCaseIndent(),
                    shouldIndentPreprocBlock,
                    getPreprocDefineIndent(),
                    getEmptyLineFill(),
                    indentableMacros );
    initContainer( preBraceHeaderStack, new vector<const string*> );
    initContainer( parenStack, new vector<int> );
    initContainer( structStack, new vector<bool> );
    initContainer( questionMarkStack, new vector<bool> );
    parenStack->emplace_back( 0 );
    initContainer( braceTypeStack, new vector<BraceType> );
    braceTypeStack->emplace_back( NULL_TYPE );
    clearFormattedLineSplitPoints();
    currentHeader = nullptr;
    currentLine = "";
    readyFormattedLine = "";
    formattedLine = "";
    verbatimDelimiter = "";
    currentChar = ' ';
    previousChar = ' ';
    previousCommandChar = ' ';
    previousNonWSChar = ' ';
    quoteChar = '"';
    preprocBlockEnd = 0;
    charNum = 0;
    checksumIn = 0;
    checksumOut = 0;
    currentLineFirstBraceNum = string::npos;
    formattedLineCommentNum = 0;
    leadingSpaces = 0;
    previousReadyFormattedLineLength = string::npos;
    preprocBraceTypeStackSize = 0;
    spacePadNum = 0;
    nextLineSpacePadNum = 0;
    objCColonAlign = 0;
    templateDepth = 0;
    squareBracketCount = 0;
    runInIndentChars = 0;
    tabIncrementIn = 0;
    previousBraceType = NULL_TYPE;
    isVirgin = true;
    isInVirginLine = true;
    isInLineComment = false;
    isInComment = false;
    isInCommentStartLine = false;
    noTrimCommentContinuation = false;
    isInPreprocessor = false;
    isInPreprocessorBeautify = false;
    doesLineStartComment = false;
    lineEndsInCommentOnly = false;
    lineIsCommentOnly = false;
    lineIsLineCommentOnly = false;
    lineIsEmpty = false;
    isImmediatelyPostCommentOnly = false;
    isImmediatelyPostEmptyLine = false;
    isInClassInitializer = false;
    isInQuote = false;
    isInVerbatimQuote = false;
    haveLineContinuationChar = false;
    isInQuoteContinuation = false;
    isHeaderInMultiStatementLine = false;
    isSpecialChar = false;
    isNonParenHeader = false;
    foundNamespaceHeader = false;
    foundClassHeader = false;
    foundStructHeader = false;
    foundInterfaceHeader = false;
    foundPreDefinitionHeader = false;
    foundPreCommandHeader = false;
    foundPreCommandMacro = false;
    foundTrailingReturnType = false;
    foundCastOperator = false;
    foundQuestionMark = false;
    isInLineBreak = false;
    endOfAsmReached = false;
    endOfCodeReached = false;
    isFormattingModeOff = false;
    isInEnum = false;
    isInExecSQL = false;
    isInAsm = false;
    isInAsmOneLine = false;
    isInAsmBlock = false;
    isLineReady = false;
    elseHeaderFollowsComments = false;
    caseHeaderFollowsComments = false;
    isPreviousBraceBlockRelated = false;
    isInPotentialCalculation = false;
    needHeaderOpeningBrace = false;
    shouldBreakLineAtNextChar = false;
    shouldKeepLineUnbroken = false;
    shouldReparseCurrentChar = false;
    passedSemicolon = false;
    passedColon = false;
    isImmediatelyPostNonInStmt = false;
    isCharImmediatelyPostNonInStmt = false;
    isInTemplate = false;
    isImmediatelyPostComment = false;
    isImmediatelyPostLineComment = false;
    isImmediatelyPostEmptyBlock = false;
    isImmediatelyPostObjCMethodPrefix = false;
    isImmediatelyPostPreprocessor = false;
    isImmediatelyPostReturn = false;
    isImmediatelyPostThrow = false;
    isImmediatelyPostNewDelete = false;
    isImmediatelyPostOperator = false;
    isImmediatelyPostTemplate = false;
    isImmediatelyPostPointerOrReference = false;
    isCharImmediatelyPostReturn = false;
    isCharImmediatelyPostThrow = false;
    isCharImmediatelyPostNewDelete = false;
    isCharImmediatelyPostOperator = false;
    isCharImmediatelyPostComment = false;
    isPreviousCharPostComment = false;
    isCharImmediatelyPostLineComment = false;
    isCharImmediatelyPostOpenBlock = false;
    isCharImmediatelyPostCloseBlock = false;
    isCharImmediatelyPostTemplate = false;
    isCharImmediatelyPostPointerOrReference = false;
    isInObjCInterface = false;
    isInObjCMethodDefinition = false;
    isInObjCReturnType = false;
    isInObjCSelector = false;
    breakCurrentOneLineBlock = false;
    shouldRemoveNextClosingBrace = false;
    isInBraceRunIn = false;
    currentLineBeginsWithBrace = false;
    isPrependPostBlockEmptyLineRequested = false;
    isAppendPostBlockEmptyLineRequested = false;
    isIndentableProprocessor = false;
    isIndentableProprocessorBlock = false;
    prependEmptyLine = false;
    appendOpeningBrace = false;
    foundClosingHeader = false;
    isImmediatelyPostHeader = false;
    isInHeader = false;
    isInCase = false;
    isFirstPreprocConditional = false;
    processedFirstConditional = false;
    isJavaStaticConstructor = false;
  }


  void ASFormatter::buildLanguageVectors() {
    if( getFileType() == formatterFileType ) {
      return;
    }
    formatterFileType = getFileType();
    headers->clear();
    nonParenHeaders->clear();
    preDefinitionHeaders->clear();
    preCommandHeaders->clear();
    operators->clear();
    assignmentOperators->clear();
    castOperators->clear();
    indentableMacros->clear();
    ASResource::buildHeaders( headers, getFileType() );
    ASResource::buildNonParenHeaders( nonParenHeaders, getFileType() );
    ASResource::buildPreDefinitionHeaders( preDefinitionHeaders, getFileType() );
    ASResource::buildPreCommandHeaders( preCommandHeaders, getFileType() );
    ASResource::buildOperators( operators, getFileType() );
    ASResource::buildAssignmentOperators( assignmentOperators );
    ASResource::buildCastOperators( castOperators );
    ASResource::buildIndentableMacros( indentableMacros );
  }


  void ASFormatter::fixOptionVariableConflicts() {
    setBraceFormatMode( ATTACH_MODE );
    setMinConditionalIndentLength();
    if( getTabLength() == 0 ) {
      setDefaultTabLength();
    }
    if( shouldAddOneLineBraces ) {
      setBreakOneLineBlocksMode( false );
    }
    if( shouldAddBraces || shouldAddOneLineBraces ) {
      setRemoveBracesMode( false );
    }
    if( getClassIndent() ) {
      setModifierIndent( false );
    }
  }

  string ASFormatter::nextLine() {
    const string* newHeader = nullptr;
    isInVirginLine = isVirgin;
    isCharImmediatelyPostComment = false;
    isPreviousCharPostComment = false;
    isCharImmediatelyPostLineComment = false;
    isCharImmediatelyPostOpenBlock = false;
    isCharImmediatelyPostCloseBlock = false;
    isCharImmediatelyPostTemplate = false;
    while( !isLineReady ) {
      if( shouldReparseCurrentChar ) {
        shouldReparseCurrentChar = false;
      } else if( !getNextChar() ) {
        breakLine();
        continue;
      } else {
        if( isInVirginLine && currentChar == '{'
            && currentLineBeginsWithBrace
            && previousCommandChar == ' ' ) {
          previousCommandChar = '{';
        }
        if( isInClassInitializer && isBraceType( braceTypeStack->back(), COMMAND_TYPE ) ) {
          isInClassInitializer = false;
        }
        if( isInBraceRunIn ) {
          isInLineBreak = false;
        }
        if( !isWhiteSpace( currentChar ) ) {
          isInBraceRunIn = false;
        }
        isPreviousCharPostComment = isCharImmediatelyPostComment;
        isCharImmediatelyPostComment = false;
        isCharImmediatelyPostTemplate = false;
        isCharImmediatelyPostReturn = false;
        isCharImmediatelyPostThrow = false;
        isCharImmediatelyPostNewDelete = false;
        isCharImmediatelyPostOperator = false;
        isCharImmediatelyPostPointerOrReference = false;
        isCharImmediatelyPostOpenBlock = false;
        isCharImmediatelyPostCloseBlock = false;
      }
      if( ( lineIsLineCommentOnly || lineIsCommentOnly )
          && currentLine.find( "*INDENT-ON*", charNum ) != string::npos && isFormattingModeOff ) {
        isFormattingModeOff = false;
        breakLine();
        formattedLine = currentLine;
        charNum = ( int ) currentLine.length() - 1;
        continue;
      }
      if( isFormattingModeOff ) {
        breakLine();
        formattedLine = currentLine;
        charNum = ( int ) currentLine.length() - 1;
        continue;
      }
      if( ( lineIsLineCommentOnly || lineIsCommentOnly ) && currentLine.find( "*INDENT-OFF*", charNum ) != string::npos ) {
        isFormattingModeOff = true;
        if( isInLineBreak ) {  // *************新行
          breakLine();
        }
        formattedLine = currentLine;
        charNum = ( int )currentLine.length() - 1;
        continue;
      }
      if( shouldBreakLineAtNextChar ) {
        if( isWhiteSpace( currentChar ) && !lineIsEmpty ) {
          continue;
        }
        isInLineBreak = true;
        shouldBreakLineAtNextChar = false;
      }
      if( isInExecSQL && !passedSemicolon ) {
        if( currentChar == ';' ) {
          passedSemicolon = true;
        }
        appendCurrentChar();
        continue;
      }
      if( isInLineComment ) {
        formatLineCommentBody();
        continue;
      } else if( isInComment ) {
        formatCommentBody();
        continue;
      } else if( isInQuote ) {
        formatQuoteBody();
        continue;
      }
      if( isSequenceReached( "//" ) ) {
        formatLineCommentOpener();
        testForTimeToSplitFormattedLine();
        continue;
      } else if( isSequenceReached( "/*" ) ) {
        formatCommentOpener();
        testForTimeToSplitFormattedLine();
        continue;
      } else if( currentChar == '"' || ( currentChar == '\'' && !isDigitSeparator( currentLine, charNum ) ) ) {
        formatQuoteOpener();
        testForTimeToSplitFormattedLine();
        continue;
      } else if( currentChar == '#' && currentLine.find_first_not_of( " \t" ) == ( size_t ) charNum ) {
        string preproc = trim( currentLine.c_str() + charNum + 1 );
        if( preproc.length() > 0 && isCharPotentialHeader( preproc, 0 )
            && ( findKeyword( preproc, 0, "region" )
                 || findKeyword( preproc, 0, "endregion" )
                 || findKeyword( preproc, 0, "error" )
                 || findKeyword( preproc, 0, "warning" )
                 || findKeyword( preproc, 0, "line" ) ) ) {
          currentLine = rtrim( currentLine );
          if( formattedLine.length() > 0 && formattedLine[0] == '{' ) {
            isInLineBreak = true;
            isInBraceRunIn = false;
          }
          if( previousCommandChar == '}' ) {
            currentHeader = nullptr;
          }
          isInLineComment = true;
          appendCurrentChar();
          continue;
        }
      }
      if( isInPreprocessor ) {
        appendCurrentChar();
        continue;
      }
      if( isInTemplate && shouldCloseTemplates ) {
        if( previousNonWSChar == '>' && isWhiteSpace( currentChar ) && peekNextChar() == '>' ) {
          continue;
        }
      }
      if( shouldRemoveNextClosingBrace && currentChar == '}' ) {
        currentLine[charNum] = currentChar = ' ';
        shouldRemoveNextClosingBrace = false;
        assert( adjustChecksumIn( -'}' ) );
        if( isEmptyLine( currentLine ) ) {
          continue;
        }
      }
      if( isWhiteSpace( currentChar ) ) {
        appendCurrentChar();
        continue;
      }
      if( currentChar == '#' ) {
        isInPreprocessor = true;
        if( formattedLine.length() > 0 && formattedLine[0] == '{' ) {
          isInLineBreak = true;
          isInBraceRunIn = false;
        }
        processPreprocessor();
        if( shouldIndentPreprocBlock && ( isBraceType( braceTypeStack->back(), NULL_TYPE )
                                          || isBraceType( braceTypeStack->back(), NAMESPACE_TYPE ) )
            && !foundClassHeader && !isInClassInitializer && sourceIterator->tellg() > preprocBlockEnd ) {
          string preproc = ASBeautifier::extractPreprocessorStatement( currentLine );
          if( preproc.length() >= 2 && preproc.substr( 0, 2 ) == "if" ) {
            if( isImmediatelyPostPreprocessor )
            { breakLine(); }
            isIndentableProprocessorBlock = isIndentablePreprocessorBlock( currentLine, charNum );
            isIndentableProprocessor = isIndentableProprocessorBlock;
          }
        }
        if( isIndentableProprocessorBlock && charNum < ( int ) currentLine.length() - 1
            && isWhiteSpace( currentLine[charNum + 1] ) ) {
          size_t nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
          if( nextText != string::npos ) {
            currentLine.erase( charNum + 1, nextText - charNum - 1 );
          }
        }
        if( isIndentableProprocessorBlock
            && sourceIterator->tellg() >= preprocBlockEnd ) {
          isIndentableProprocessorBlock = false;
        }
      }
      if( isImmediatelyPostComment ) {
        caseHeaderFollowsComments = false;
        isImmediatelyPostComment = false;
        isCharImmediatelyPostComment = true;
      }
      if( isImmediatelyPostLineComment ) {
        caseHeaderFollowsComments = false;
        isImmediatelyPostLineComment = false;
        isCharImmediatelyPostLineComment = true;
      }
      if( isImmediatelyPostReturn ) {
        isImmediatelyPostReturn = false;
        isCharImmediatelyPostReturn = true;
      }
      if( isImmediatelyPostThrow ) {
        isImmediatelyPostThrow = false;
        isCharImmediatelyPostThrow = true;
      }
      if( isImmediatelyPostNewDelete ) {
        isImmediatelyPostNewDelete = false;
        isCharImmediatelyPostNewDelete = true;
      }
      if( isImmediatelyPostOperator ) {
        isImmediatelyPostOperator = false;
        isCharImmediatelyPostOperator = true;
      }
      if( isImmediatelyPostTemplate ) {
        isImmediatelyPostTemplate = false;
        isCharImmediatelyPostTemplate = true;
      }
      if( isImmediatelyPostPointerOrReference ) {
        isImmediatelyPostPointerOrReference = false;
        isCharImmediatelyPostPointerOrReference = true;
      }
      if( isImmediatelyPostHeader ) {
        if( currentChar != '{' && shouldAddBraces && ( shouldBreakOneLineStatements || !isHeaderInMultiStatementLine ) && isOkToBreakBlock( braceTypeStack->back() ) ) {
          bool bracesAdded = addBracesToStatement();
          if( bracesAdded && !shouldAddOneLineBraces ) {
            size_t firstText = currentLine.find_first_not_of( " \t" );
            assert( firstText != string::npos );
            if( ( int ) firstText == charNum || shouldBreakOneLineHeaders ) {
              breakCurrentOneLineBlock = true;
            }
          }
        } else if( currentChar == '{' && shouldRemoveBraces ) {
          bool bracesRemoved = removeBracesFromStatement();
          if( bracesRemoved ) {
            shouldRemoveNextClosingBrace = true;
            if( isBeforeAnyLineEndComment( charNum ) ) {
              spacePadNum--;
            } else if( shouldBreakOneLineBlocks || ( currentLineBeginsWithBrace
                       && currentLine.find_first_not_of( " \t" ) != string::npos ) ) {
              shouldBreakLineAtNextChar = true;
            }
            continue;
          }
        }
        if( shouldBreakElseIfs
            && currentHeader == &AS_ELSE
            && isOkToBreakBlock( braceTypeStack->back() )
            && !isBeforeAnyComment()
            && ( shouldBreakOneLineStatements || !isHeaderInMultiStatementLine ) ) {
          string nextText = peekNextText( currentLine.substr( charNum ) );
          if( nextText.length() > 0
              && isCharPotentialHeader( nextText, 0 )
              && ASBase::findHeader( nextText, 0, headers ) == &AS_IF ) {
            isInLineBreak = true;
          }
        }
        if( shouldBreakOneLineHeaders && peekNextChar() != ' ' && ( shouldBreakOneLineStatements || ( !isHeaderInMultiStatementLine
            && !isMultiStatementLine() ) ) && isOkToBreakBlock( braceTypeStack->back() ) && !isBeforeAnyComment() ) {
          if( currentChar == '{' ) {
            if( !currentLineBeginsWithBrace ) {
              if( isOneLineBlockReached( currentLine, charNum ) == 3 ) {
                isInLineBreak = false;
              } else {
                breakCurrentOneLineBlock = true;
              }
            }
          } else if( currentHeader == &AS_ELSE ) {
            string nextText = peekNextText( currentLine.substr( charNum ), true );
            if( nextText.length() > 0 && ( ( isCharPotentialHeader( nextText, 0 ) && ASBase::findHeader( nextText, 0, headers ) != &AS_IF )
                                           || nextText[0] == '{' ) ) {
              isInLineBreak = true;
            }
          } else {
            isInLineBreak = true;
          }
        }
        isImmediatelyPostHeader = false;
      }
      if( passedSemicolon ) {
        passedSemicolon = false;
        if( parenStack->back() == 0 && !isCharImmediatelyPostComment && currentChar != ';' ) {
          if( isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE ) ) {
            size_t blockEnd = currentLine.rfind( AS_CLOSE_BRACE );
            assert( blockEnd != string::npos );
            if( isBeforeAnyLineEndComment( blockEnd ) ) {
              size_t commentStart = currentLine.find_first_not_of( " \t", blockEnd + 1 );
              assert( commentStart != string::npos );
              assert( ( currentLine.compare( commentStart, 2, "//" ) == 0 )
                      || ( currentLine.compare( commentStart, 2, "/*" ) == 0 ) );
              formattedLine.append( getIndentLength() - 1, ' ' );
              int charNumSave = charNum;
              charNum = commentStart;
              while( charNum < ( int ) currentLine.length() ) {
                currentChar = currentLine[charNum];
                if( currentChar == '\t' && shouldConvertTabs ) {
                  convertTabToSpaces();
                }
                formattedLine.append( 1, currentChar );
                ++charNum;
              }
              size_t commentLength = currentLine.length() - commentStart;
              currentLine.erase( commentStart, commentLength );
              charNum = charNumSave;
              currentChar = currentLine[charNum];
              testForTimeToSplitFormattedLine();
            }
          }
          isInExecSQL = false;
          shouldReparseCurrentChar = true;
          if( formattedLine.find_first_not_of( " \t" ) != string::npos ) {
            isInLineBreak = true;
          }
          if( needHeaderOpeningBrace ) {
            isCharImmediatelyPostCloseBlock = true;
            needHeaderOpeningBrace = false;
          }
          continue;
        }
      }
      if( passedColon ) {
        passedColon = false;
        if( parenStack->back() == 0 && !isBeforeAnyComment() && ( formattedLine.find_first_not_of( " \t" ) != string::npos ) ) {
          shouldReparseCurrentChar = true;
          isInLineBreak = true;
          continue;
        }
      }
      if( !isInTemplate && currentChar == '<' ) {
        checkIfTemplateOpener();
      }
      if( currentChar == '(' || currentChar == '[' || ( isInTemplate && currentChar == '<' ) ) {
        questionMarkStack->push_back( foundQuestionMark );
        foundQuestionMark = false;
        parenStack->back()++;
        if( currentChar == '[' ) {
          ++squareBracketCount;
          if( getAlignMethodColon() && squareBracketCount == 1 && isCStyle() ) {
            objCColonAlign = findObjCColonAlignment();
          }
        }
      } else if( currentChar == ')' || currentChar == ']' || ( isInTemplate && currentChar == '>' ) ) {
        foundPreCommandHeader = false;
        parenStack->back()--;
        if( parenStack->back() < 0 ) {
          parenStack->back() = 0;
        }
        if( !questionMarkStack->empty() ) {
          foundQuestionMark = questionMarkStack->back();
          questionMarkStack->pop_back();
        }
        if( isInTemplate && currentChar == '>' ) {
          templateDepth--;
          if( templateDepth == 0 ) {
            isInTemplate = false;
            isImmediatelyPostTemplate = true;
          }
        }
        if( isInHeader && parenStack->back() == 0 ) {
          isInHeader = false;
          isImmediatelyPostHeader = true;
          foundQuestionMark = false;
        }
        if( currentChar == ']' ) {
          --squareBracketCount;
          if( squareBracketCount <= 0 ) {
            squareBracketCount = 0;
            objCColonAlign = 0;
          }
        }
        if( currentChar == ')' ) {
          foundCastOperator = false;
          if( parenStack->back() == 0 ) {
            endOfAsmReached = true;
          }
        }
      }
      if( currentChar == '{' || currentChar == '}' ) {
        if( currentChar == '{' && !appendOpeningBrace ) {
          BraceType newBraceType = getBraceType();
          breakCurrentOneLineBlock = false;
          foundNamespaceHeader = false;
          foundClassHeader = false;
          foundStructHeader = false;
          foundInterfaceHeader = false;
          foundPreDefinitionHeader = false;
          foundPreCommandHeader = false;
          foundPreCommandMacro = false;
          foundTrailingReturnType = false;
          isInPotentialCalculation = false;
          isInObjCMethodDefinition = false;
          isInObjCInterface = false;
          isInEnum = false;
          isJavaStaticConstructor = false;
          isCharImmediatelyPostNonInStmt = false;
          needHeaderOpeningBrace = false;
          shouldKeepLineUnbroken = false;
          objCColonAlign = 0;
          isPreviousBraceBlockRelated = !isBraceType( newBraceType, ARRAY_TYPE );
          braceTypeStack->emplace_back( newBraceType );//BREAK_BLOCK_TYPE
          preBraceHeaderStack->emplace_back( currentHeader );
          currentHeader = nullptr;
          structStack->push_back( isInIndentableStruct );
          if( isBraceType( newBraceType, STRUCT_TYPE ) && isCStyle() ) {
            isInIndentableStruct = isStructAccessModified( currentLine, charNum );
          } else {
            isInIndentableStruct = false;
          }
        }
        BraceType braceType = braceTypeStack->back();
        bool isOpeningArrayBrace = ( isBraceType( braceType, ARRAY_TYPE ) && braceTypeStack->size() >= 2
                                     && !isBraceType( ( *braceTypeStack )[braceTypeStack->size() - 2], ARRAY_TYPE ) );
        if( currentChar == '}' ) {
          isAppendPostBlockEmptyLineRequested = false;
          if( isInAsm ) {
            endOfAsmReached = true;
          }
          isInAsmOneLine = isInQuote = false;
          shouldKeepLineUnbroken = false;
          squareBracketCount = 0;
          if( braceTypeStack->size() > 1 ) {
            previousBraceType = braceTypeStack->back();
            braceTypeStack->pop_back();
            isPreviousBraceBlockRelated = !isBraceType( braceType, ARRAY_TYPE );
          } else {
            previousBraceType = NULL_TYPE;
            isPreviousBraceBlockRelated = false;
          }
          if( !preBraceHeaderStack->empty() ) {
            currentHeader = preBraceHeaderStack->back();
            preBraceHeaderStack->pop_back();
          } else
          { currentHeader = nullptr; }
          if( !structStack->empty() ) {
            isInIndentableStruct = structStack->back();
            structStack->pop_back();
          } else
          { isInIndentableStruct = false; }
          if( isNonInStatementArray
              && ( !isBraceType( braceTypeStack->back(), ARRAY_TYPE )
                   || peekNextChar() == ';' ) ) {
            isImmediatelyPostNonInStmt = true;
          }
          if( !shouldBreakOneLineStatements
              && ASBeautifier::getNextWord( currentLine, charNum ) == AS_ELSE ) {
            size_t nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
            if( ASBeautifier::peekNextChar( currentLine, nextText + 3 ) == ' ' )
            { shouldBreakLineAtNextChar = true; }
          }
        }
        appendOpeningBrace = false;
        if( isBraceType( braceType, ARRAY_TYPE ) ) {
          formatArrayBraces( braceType, isOpeningArrayBrace );
        } else {
          if( currentChar == '{' ) {
            formatOpeningBrace( braceType );
          } else {
            formatClosingBrace( braceType );
          }
        }
        continue;
      }
      if( ( ( ( previousCommandChar == '{' && isPreviousBraceBlockRelated )
              || ( ( previousCommandChar == '}'
                     && !isImmediatelyPostEmptyBlock
                     && isPreviousBraceBlockRelated
                     && !isPreviousCharPostComment
                     && peekNextChar() != ' '
                     && !isBraceType( previousBraceType, DEFINITION_TYPE ) )
                   && !isBraceType( braceTypeStack->back(), DEFINITION_TYPE ) ) )
            && isOkToBreakBlock( braceTypeStack->back() ) )
          || ( previousCommandChar == '{'
               && isBraceType( braceTypeStack->back(), ARRAY_TYPE )
               && !isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE )
               && isNonInStatementArray )
          || ( formattingStyle == STYLE_PICO
               && ( previousCommandChar == '{' && isPreviousBraceBlockRelated )
               && isBraceType( braceTypeStack->back(), COMMAND_TYPE )
               && isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE )
               && braceFormatMode == RUN_IN_MODE ) ) {
        isCharImmediatelyPostOpenBlock = ( previousCommandChar == '{' );
        isCharImmediatelyPostCloseBlock = ( previousCommandChar == '}' );
        if( isCharImmediatelyPostOpenBlock && !isCharImmediatelyPostComment
            && !isCharImmediatelyPostLineComment ) {
          previousCommandChar = ' ';
          if( braceFormatMode == NONE_MODE ) {
            if( isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE )
                && ( isBraceType( braceTypeStack->back(), BREAK_BLOCK_TYPE )
                     || shouldBreakOneLineBlocks ) ) {
              isInLineBreak = true;
            } else if( currentLineBeginsWithBrace ) {
              formatRunIn();
            } else {
              breakLine();
            }
          } else if( braceFormatMode == RUN_IN_MODE
                     && currentChar != '#' ) {
            formatRunIn();
          } else
          { isInLineBreak = true; }
        } else if( isCharImmediatelyPostCloseBlock
                   && shouldBreakOneLineStatements
                   && !isCharImmediatelyPostComment
                   && ( ( isLegalNameChar( currentChar ) && currentChar != '.' )
                        || currentChar == '+'
                        || currentChar == '-'
                        || currentChar == '*'
                        || currentChar == '&'
                        || currentChar == '(' ) ) {
          previousCommandChar = ' ';
          isInLineBreak = true;
        }
      }
      isImmediatelyPostEmptyBlock = false;
      bool isPotentialHeader = isCharPotentialHeader( currentLine, charNum );
      if( isPotentialHeader && !isInTemplate && squareBracketCount == 0 ) {
        isNonParenHeader = false;
        foundClosingHeader = false;
        newHeader = findHeader( headers );
        if( isCStyle()
            && ( newHeader == &AS_FOREVER || newHeader == &AS_FOREACH ) ) {
          if( currentLine.find_first_of( "=;", charNum ) != string::npos ) {
            newHeader = nullptr;
          }
        }
        if( isJavaStyle()
            && ( newHeader == &AS_SYNCHRONIZED ) ) {
          if( !isBraceType( braceTypeStack->back(), COMMAND_TYPE ) ) {
            newHeader = nullptr;
          }
        } else if( newHeader == &AS_USING
                   && ASBeautifier::peekNextChar(
                     currentLine, charNum + ( *newHeader ).length() - 1 ) != '(' ) {
          newHeader = nullptr;
        }
        if( newHeader != nullptr ) {
          foundClosingHeader = isClosingHeader( newHeader );
          if( !foundClosingHeader ) {
            if( ( newHeader == &AS_WHILE && currentHeader == &AS_DO )
                || ( newHeader == &_AS_FINALLY && currentHeader == &_AS_TRY )
                || ( newHeader == &_AS_EXCEPT && currentHeader == &_AS_TRY ) )
            { foundClosingHeader = true; }
            else if( isSharpStyle()
                     && previousNonWSChar == '}'
                     && ( ( newHeader == &AS_SET && currentHeader == &AS_GET )
                          || ( newHeader == &AS_REMOVE && currentHeader == &AS_ADD ) )
                     && isOkToBreakBlock( braceTypeStack->back() ) )
            { isAppendPostBlockEmptyLineRequested = false; }
          }
          if( isSharpStyle()
              && ( ( newHeader == &AS_SET && currentHeader == &AS_GET )
                   || ( newHeader == &AS_REMOVE && currentHeader == &AS_ADD ) )
              && !isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE )
              && currentLine[currentLine.find_first_not_of( " \t" )] == '}' ) {
            isInLineBreak = true;
          }
          const string* previousHeader = currentHeader;
          currentHeader = newHeader;
          needHeaderOpeningBrace = true;
          if( ( previousNonWSChar == ';' || previousNonWSChar == ':' )
              && !isInLineBreak
              && isOkToBreakBlock( braceTypeStack->back() ) ) {
            if( maxCodeLength != string::npos
                && previousHeader != &AS_CASE )
            { isInLineBreak = true; }
            else
            { isHeaderInMultiStatementLine = true; }
          }
          if( foundClosingHeader && previousNonWSChar == '}' ) {
            if( isOkToBreakBlock( braceTypeStack->back() ) )
            { isLineBreakBeforeClosingHeader(); }
            if( isInLineBreak ) {   // *************新行
              nextLineSpacePadNum = getNextLineCommentAdjustment();
            } else {
              spacePadNum = getCurrentLineCommentAdjustment();
            }
          }
          isNonParenHeader = findHeader( nonParenHeaders ) != nullptr;
          if( isNonParenHeader
              && ( currentHeader == &AS_CATCH
                   || currentHeader == &AS_CASE ) ) {
            int startChar = charNum + currentHeader->length() - 1;
            if( ASBeautifier::peekNextChar( currentLine, startChar ) == '(' )
            { isNonParenHeader = false; }
          }
          if( currentHeader == &AS_IF
              && previousHeader == &AS_ELSE
              && isInLineBreak
              && !shouldBreakElseIfs
              && !isCharImmediatelyPostLineComment
              && !isImmediatelyPostPreprocessor ) {
            size_t start = formattedLine.length() >= 6 ? formattedLine.length() - 6 : 0;
            if( formattedLine.find( AS_ELSE, start ) != string::npos ) {
              appendSpacePad();
              isInLineBreak = false;
            }
          }
          appendSequence( *currentHeader );
          goForward( currentHeader->length() - 1 );
          if( shouldPadHeader
              && !isNonParenHeader
              && charNum < ( int ) currentLine.length() - 1 && !isWhiteSpace( currentLine[charNum + 1] ) ) {
            appendSpacePad();
          }
          if( currentHeader != &AS_CASE && currentHeader != &AS_DEFAULT
              && !( foundClosingHeader && currentHeader == &AS_WHILE ) ) {
            isInHeader = true;
            if( isNonParenHeader && !isSharpStyleWithParen( currentHeader ) ) {
              isImmediatelyPostHeader = true;
              isInHeader = false;
            }
          }
          if( shouldBreakBlocks
              && isOkToBreakBlock( braceTypeStack->back() )
              && !isHeaderInMultiStatementLine ) {
            if( previousHeader == nullptr
                && !foundClosingHeader
                && !isCharImmediatelyPostOpenBlock
                && !isImmediatelyPostCommentOnly )
            { isPrependPostBlockEmptyLineRequested = true; }
            if( isClosingHeader( currentHeader )
                || foundClosingHeader )
            { isPrependPostBlockEmptyLineRequested = false; }
            if( shouldBreakClosingHeaderBlocks
                && isCharImmediatelyPostCloseBlock
                && !isImmediatelyPostCommentOnly
                && !( currentHeader == &AS_WHILE
                      && foundClosingHeader ) )
            { isPrependPostBlockEmptyLineRequested = true; }
          }
          if( currentHeader == &AS_CASE
              || currentHeader == &AS_DEFAULT ) {
            isInCase = true;
          }
          continue;
        } else if( ( newHeader = findHeader( preDefinitionHeaders ) ) != nullptr
                   && parenStack->back() == 0
                   && !isInEnum ) {
          if( newHeader == &AS_NAMESPACE || newHeader == &AS_MODULE ) {
            foundNamespaceHeader = true;
          }
          if( newHeader == &AS_CLASS ) {
            foundClassHeader = true;
          }
          if( newHeader == &AS_STRUCT ) {
            foundStructHeader = true;
          }
          if( newHeader == &AS_INTERFACE ) {
            foundInterfaceHeader = true;
          }
          foundPreDefinitionHeader = true;
          appendSequence( *newHeader );
          goForward( newHeader->length() - 1 );
          continue;
        } else if( ( newHeader = findHeader( preCommandHeaders ) ) != nullptr ) {
          if( previousNonWSChar == ')' ) {
            foundPreCommandHeader = true;
          }
        } else if( ( newHeader = findHeader( castOperators ) ) != nullptr ) {
          foundCastOperator = true;
          appendSequence( *newHeader );
          goForward( newHeader->length() - 1 );
          continue;
        }
      }
      if( isInLineBreak ) {  // *************新行
        breakLine();
        if( isInVirginLine ) {
          lineCommentNoBeautify = lineCommentNoIndent;
          lineCommentNoIndent = false;
          if( isImmediatelyPostPreprocessor ) {
            isInIndentablePreproc = isIndentableProprocessor;
            isIndentableProprocessor = false;
          }
        }
      }
      if( previousNonWSChar == '}' || currentChar == ';' ) {
        if( currentChar == ';' ) {
          squareBracketCount = 0;
          if( ( ( shouldBreakOneLineStatements
                  || isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE ) )
                && isOkToBreakBlock( braceTypeStack->back() ) )
              && !( attachClosingBraceMode && peekNextChar() == '}' ) ) {
            passedSemicolon = true;
          } else if( !shouldBreakOneLineStatements
                     && ASBeautifier::getNextWord( currentLine, charNum ) == AS_ELSE ) {
            size_t nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
            if( ASBeautifier::peekNextChar( currentLine, nextText + 3 ) == ' ' )
            { passedSemicolon = true; }
          }
          if( shouldBreakBlocks
              && currentHeader != nullptr
              && currentHeader != &AS_CASE
              && currentHeader != &AS_DEFAULT
              && !isHeaderInMultiStatementLine
              && parenStack->back() == 0 ) {
            isAppendPostBlockEmptyLineRequested = true;
          }
        }
        if( currentChar != ';'
            || ( needHeaderOpeningBrace && parenStack->back() == 0 ) ) {
          currentHeader = nullptr;
        }
        resetEndOfStatement();
      }
      if( currentChar == ':'
          && previousChar != ':'
          && peekNextChar() != ':' ) {
        if( isInCase ) {
          isInCase = false;
          if( shouldBreakOneLineStatements ) {
            passedColon = true;
          }
        } else if( isCStyle()
                   && isOkToBreakBlock( braceTypeStack->back() )
                   && shouldBreakOneLineStatements
                   && !foundQuestionMark
                   && !foundPreDefinitionHeader
                   && previousCommandChar != ')'
                   && !foundPreCommandHeader
                   && squareBracketCount == 0
                   && !isInObjCMethodDefinition
                   && !isInObjCInterface
                   && !isInObjCSelector
                   && !isDigit( peekNextChar() )
                   && !isInEnum
                   && !isInAsm
                   && !isInAsmOneLine
                   && !isInAsmBlock ) {
          passedColon = true;
        }
        if( isCStyle()
            && shouldPadMethodColon
            && ( squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector )
            && !foundQuestionMark ) {
          padObjCMethodColon();
        }
        if( isInObjCInterface ) {
          appendSpacePad();
          if( ( int ) currentLine.length() > charNum + 1
              && !isWhiteSpace( currentLine[charNum + 1] ) ) {
            currentLine.insert( charNum + 1, " " );
          }
        }
        if( isClassInitializer() ) {
          isInClassInitializer = true;
        }
      }
      if( currentChar == '?' ) {
        foundQuestionMark = true;
      }
      if( isPotentialHeader && !isInTemplate ) {
        if( findKeyword( currentLine, charNum, AS_NEW )
            || findKeyword( currentLine, charNum, AS_DELETE ) ) {
          isInPotentialCalculation = false;
          isImmediatelyPostNewDelete = true;
        }
        if( findKeyword( currentLine, charNum, AS_RETURN ) ) {
          isInPotentialCalculation = true;
          isImmediatelyPostReturn = true;
        }
        if( findKeyword( currentLine, charNum, AS_OPERATOR ) ) {
          isImmediatelyPostOperator = true;
        }
        if( findKeyword( currentLine, charNum, AS_ENUM ) ) {
          size_t firstNum = currentLine.find_first_of( "(){},/" );
          if( firstNum == string::npos
              || currentLine[firstNum] == '{'
              || currentLine[firstNum] == '/' ) {
            isInEnum = true;
          }
        }
        if( isCStyle()
            && findKeyword( currentLine, charNum, AS_THROW )
            && previousCommandChar != ')'
            && !foundPreCommandHeader ) {
          isImmediatelyPostThrow = true;
        }
        if( isCStyle() && findKeyword( currentLine, charNum, AS_EXTERN ) && isExternC() ) {
          isInExternC = true;
        }
        if( isCStyle() && findKeyword( currentLine, charNum, AS_AUTO )
            && ( isBraceType( braceTypeStack->back(), NULL_TYPE )
                 || isBraceType( braceTypeStack->back(), NAMESPACE_TYPE )
                 || isBraceType( braceTypeStack->back(), CLASS_TYPE ) ) ) {
          foundTrailingReturnType = true;
        }
        if( isCStyle() && findKeyword( currentLine, charNum, AS_NS_DURING ) ) {
          foundPreCommandMacro = true;
        }
        if( isCStyle() && findKeyword( currentLine, charNum, AS_NS_HANDLER ) ) {
          foundPreCommandMacro = true;
        }
        if( isCStyle() && isExecSQL( currentLine, charNum ) ) {
          isInExecSQL = true;
        }
        if( isCStyle() ) {
          if( findKeyword( currentLine, charNum, AS_ASM )
              || findKeyword( currentLine, charNum, AS__ASM__ ) ) {
            isInAsm = true;
          } else if( findKeyword( currentLine, charNum, AS_MS_ASM )
                     || findKeyword( currentLine, charNum, AS_MS__ASM ) ) {
            int index = 4;
            if( peekNextChar() == '_' )
            { index = 5; }
            char peekedChar = ASBase::peekNextChar( currentLine, charNum + index );
            if( peekedChar == '{' || peekedChar == ' ' )
            { isInAsmBlock = true; }
            else
            { isInAsmOneLine = true; }
          }
        }
        if( isJavaStyle()
            && ( findKeyword( currentLine, charNum, AS_STATIC )
                 && isNextCharOpeningBrace( charNum + 6 ) ) ) {
          isJavaStaticConstructor = true;
        }
        if( isSharpStyle()
            && ( findKeyword( currentLine, charNum, AS_DELEGATE )
                 || findKeyword( currentLine, charNum, AS_UNCHECKED ) ) ) {
          isSharpDelegate = true;
        }
        string name = getCurrentWord( currentLine, charNum );
        if( name == "and" || name == "or" ) {
          if( shouldPadOperators && previousNonWSChar != ':' ) {
            appendSpacePad();
            appendOperator( name );
            goForward( name.length() - 1 );
            if( !isBeforeAnyComment()
                && !( currentLine.compare( charNum + 1, 1, AS_SEMICOLON ) == 0 )
                && !( currentLine.compare( charNum + 1, 2, AS_SCOPE_RESOLUTION ) == 0 ) )
            { appendSpaceAfter(); }
          } else {
            appendOperator( name );
            goForward( name.length() - 1 );
          }
        } else {
          appendSequence( name );
          goForward( name.length() - 1 );
        }
        continue;
      }
      if( currentChar == '@'
          && isCharPotentialHeader( currentLine, charNum + 1 )
          && findKeyword( currentLine, charNum + 1, AS_INTERFACE )
          && isBraceType( braceTypeStack->back(), NULL_TYPE ) ) {
        isInObjCInterface = true;
        string name = '@' + AS_INTERFACE;
        appendSequence( name );
        goForward( name.length() - 1 );
        continue;
      } else if( currentChar == '@'
                 && isCharPotentialHeader( currentLine, charNum + 1 )
                 && findKeyword( currentLine, charNum + 1, AS_SELECTOR ) ) {
        isInObjCSelector = true;
        string name = '@' + AS_SELECTOR;
        appendSequence( name );
        goForward( name.length() - 1 );
        continue;
      } else if( ( currentChar == '-' || currentChar == '+' )
                 && ( int ) currentLine.find_first_not_of( " \t" ) == charNum
                 && peekNextChar() == '('
                 && isBraceType( braceTypeStack->back(), NULL_TYPE )
                 && !isInPotentialCalculation ) {
        isInObjCMethodDefinition = true;
        isImmediatelyPostObjCMethodPrefix = true;
        isInObjCInterface = false;
        if( getAlignMethodColon() ) {
          objCColonAlign = findObjCColonAlignment();
        }
        appendCurrentChar();
        continue;
      }
      bool isPotentialOperator = isCharPotentialOperator( currentChar );
      newHeader = nullptr;
      if( isPotentialOperator ) {
        newHeader = findOperator( operators );
        if( newHeader != nullptr
            && newHeader == &AS_GCC_MIN_ASSIGN
            && isJavaStyle()
            && isInTemplate ) {
          newHeader = nullptr;
        }
        if( newHeader != nullptr ) {
          if( newHeader == &AS_LAMBDA ) {
            foundPreCommandHeader = true;
          }
          if( isInTemplate && ( newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR ) ) {
            newHeader = &AS_GR;
          }
          if( !isInPotentialCalculation ) {
            if( find( begin( *assignmentOperators ), end( *assignmentOperators ), newHeader )
                != end( *assignmentOperators ) ) {
              foundPreCommandHeader = false;
              char peekedChar = peekNextChar();
              isInPotentialCalculation = !( newHeader == &AS_EQUAL && peekedChar == '*' )
                                         && !( newHeader == &AS_EQUAL && peekedChar == '&' )
                                         && !isCharImmediatelyPostOperator;
            }
          }
        }
      }
      if( newHeader != nullptr && !isJavaStyle()
          && ( newHeader == &AS_MULT
               || newHeader == &AS_BIT_AND
               || newHeader == &AS_BIT_XOR
               || newHeader == &AS_AND )
          && isPointerOrReference() ) {
        if( !isDereferenceOrAddressOf() && !isOperatorPaddingDisabled() ) {
          formatPointerOrReference();
        } else {
          appendOperator( *newHeader );
          goForward( newHeader->length() - 1 );
        }
        isImmediatelyPostPointerOrReference = true;
        continue;
      }
      if( shouldPadOperators && newHeader != nullptr && !isOperatorPaddingDisabled() ) {
        padOperators( newHeader );
        continue;
      }
      if( currentChar == ',' ) {
        const size_t len = formattedLine.length();
        size_t lastText = formattedLine.find_last_not_of( ' ' );
        if( lastText != string::npos && lastText < len - 1 ) {
          formattedLine.resize( lastText + 1 );
          int size_diff = len - ( lastText + 1 );
          spacePadNum -= size_diff;
        }
      }
      if( currentChar == ';' || ( currentChar == ',' && ( shouldPadOperators || shouldPadCommas ) ) ) {
        char nextChar = ' ';
        if( charNum + 1 < ( int ) currentLine.length() ) {
          nextChar = currentLine[charNum + 1];
        }
        if( !isWhiteSpace( nextChar )
            && nextChar != '}'
            && nextChar != ')'
            && nextChar != ']'
            && nextChar != '>'
            && nextChar != ';'
            && !isBeforeAnyComment()
          ) {
          appendCurrentChar();
          appendSpaceAfter();
          continue;
        }
      }
      if( currentChar == '(' || currentChar == ')' ) {
        if( currentChar == '(' ) {
          if( shouldPadHeader
              && ( isCharImmediatelyPostReturn
                   || isCharImmediatelyPostThrow
                   || isCharImmediatelyPostNewDelete ) ) {
            appendSpacePad();
          }
        }
        if( shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen ) {
          padParens();
        } else
        { appendCurrentChar(); }
        if( isInObjCMethodDefinition ) {
          if( currentChar == '(' && isImmediatelyPostObjCMethodPrefix ) {
            if( shouldPadMethodPrefix || shouldUnPadMethodPrefix )
            { padObjCMethodPrefix(); }
            isImmediatelyPostObjCMethodPrefix = false;
            isInObjCReturnType = true;
          } else if( currentChar == ')' && isInObjCReturnType ) {
            if( shouldPadReturnType || shouldUnPadReturnType )
            { padObjCReturnType(); }
            isInObjCReturnType = false;
          } else if( shouldPadParamType || shouldUnPadParamType ) {
            padObjCParamType();
          }
        }
        continue;
      }
      if( newHeader != nullptr ) {
        appendOperator( *newHeader );
        goForward( newHeader->length() - 1 );
        continue;
      }
      appendCurrentChar();
    }
    string beautifiedLine;
    size_t readyFormattedLineLength = trim( readyFormattedLine ).length();
    bool isInNamespace = isBraceType( braceTypeStack->back(), NAMESPACE_TYPE );
    if( prependEmptyLine
        && readyFormattedLineLength > 0
        && previousReadyFormattedLineLength > 0 ) {
      isLineReady = true;
      beautifiedLine = beautify( "" );
      previousReadyFormattedLineLength = 0;
      enhancer->enhance( beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL );
    } else {
      isLineReady = false;
      runInIndentContinuation = runInIndentChars;
      beautifiedLine = beautify( readyFormattedLine );
      previousReadyFormattedLineLength = readyFormattedLineLength;
      if( !lineCommentNoBeautify && !isFormattingModeOff ) {
        enhancer->enhance( beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL );
      }
      runInIndentChars = 0;
      lineCommentNoBeautify = lineCommentNoIndent;
      lineCommentNoIndent = false;
      isInIndentablePreproc = isIndentableProprocessor;
      isIndentableProprocessor = false;
      isElseHeaderIndent = elseHeaderFollowsComments;
      isCaseHeaderCommentIndent = caseHeaderFollowsComments;
      objCColonAlignSubsequent = objCColonAlign;
      if( isCharImmediatelyPostNonInStmt ) {
        isNonInStatementArray = false;
        isCharImmediatelyPostNonInStmt = false;
      }
      isInPreprocessorBeautify = isInPreprocessor;
      isInBeautifySQL = isInExecSQL;
    }
    prependEmptyLine = false;
    assert( computeChecksumOut( beautifiedLine ) );
    return beautifiedLine;
  }
  bool ASFormatter::hasMoreLines() const {
    return !endOfCodeReached;
  }
  bool ASFormatter::isBraceType( BraceType a, BraceType b ) const {
    if( a == NULL_TYPE || b == NULL_TYPE ) {
      return ( a == b );
    }
    return ( ( a & b ) == b );
  }
  void ASFormatter::setFormattingStyle( FormatStyle style ) {
    formattingStyle = style;
  }
  void ASFormatter::setAddBracesMode( bool state ) {
    shouldAddBraces = state;
  }
  void ASFormatter::setAddOneLineBracesMode( bool state ) {
    shouldAddBraces = state;
    shouldAddOneLineBraces = state;
  }
  void ASFormatter::setRemoveBracesMode( bool state ) {
    shouldRemoveBraces = state;
  }
  void ASFormatter::setAddBracketsMode( bool state ) {
    setAddBracesMode( state );
  }
  void ASFormatter::setAddOneLineBracketsMode( bool state ) {
    setAddOneLineBracesMode( state );
  }
  void ASFormatter::setRemoveBracketsMode( bool state ) {
    setRemoveBracesMode( state );
  }
  void ASFormatter::setBreakClosingHeaderBracketsMode( bool state ) {
    setBreakClosingHeaderBracesMode( state );
  }
  void ASFormatter::setBraceFormatMode( BraceMode mode ) {
    braceFormatMode = mode;
  }
  void ASFormatter::setBreakAfterMode( bool state ) {
    shouldBreakLineAfterLogical = state;
  }
  void ASFormatter::setBreakClosingHeaderBracesMode( bool state ) {
    shouldBreakClosingHeaderBraces = state;
  }
  void ASFormatter::setBreakElseIfsMode( bool state ) {
    shouldBreakElseIfs = state;
  }
  void ASFormatter::setCommaPaddingMode( bool state ) {
    shouldPadCommas = state;
  }
  void ASFormatter::setMaxCodeLength( int max ) {
    maxCodeLength = max;
  }
  void ASFormatter::setOperatorPaddingMode( bool state ) {
    shouldPadOperators = state;
  }
  void ASFormatter::setParensOutsidePaddingMode( bool state ) {
    shouldPadParensOutside = state;
  }
  void ASFormatter::setParensInsidePaddingMode( bool state ) {
    shouldPadParensInside = state;
  }
  void ASFormatter::setParensFirstPaddingMode( bool state ) {
    shouldPadFirstParen = state;
  }
  void ASFormatter::setParensHeaderPaddingMode( bool state ) {
    shouldPadHeader = state;
  }
  void ASFormatter::setParensUnPaddingMode( bool state ) {
    shouldUnPadParens = state;
  }
  void ASFormatter::setPreprocBlockIndent( bool state ) {
    shouldIndentPreprocBlock = state;
  }
  void ASFormatter::setStripCommentPrefix( bool state ) {
    shouldStripCommentPrefix = state;
  }
  void ASFormatter::setMethodPrefixPaddingMode( bool state ) {
    shouldPadMethodPrefix = state;
  }
  void ASFormatter::setMethodPrefixUnPaddingMode( bool state ) {
    shouldUnPadMethodPrefix = state;
  }
  void ASFormatter::setReturnTypePaddingMode( bool state ) {
    shouldPadReturnType = state;
  }
  void ASFormatter::setReturnTypeUnPaddingMode( bool state ) {
    shouldUnPadReturnType = state;
  }
  void ASFormatter::setParamTypePaddingMode( bool state ) {
    shouldPadParamType = state;
  }
  void ASFormatter::setParamTypeUnPaddingMode( bool state ) {
    shouldUnPadParamType = state;
  }
  void ASFormatter::setObjCColonPaddingMode( ObjCColonPad mode ) {
    shouldPadMethodColon = true;
    objCColonPadMode = mode;
  }
  void ASFormatter::setAttachClosingBraceMode( bool state ) {
    attachClosingBraceMode = state;
  }
  void ASFormatter::setAttachClass( bool state ) {
    shouldAttachClass = state;
  }
  void ASFormatter::setAttachExternC( bool state ) {
    shouldAttachExternC = state;
  }
  void ASFormatter::setAttachNamespace( bool state ) {
    shouldAttachNamespace = state;
  }
  void ASFormatter::setAttachInline( bool state ) {
    shouldAttachInline = state;
  }
  void ASFormatter::setAttachClosingWhile( bool state ) {
    shouldAttachClosingWhile = state;
  }
  void ASFormatter::setBreakOneLineBlocksMode( bool state ) {
    shouldBreakOneLineBlocks = state;
  }
  void ASFormatter::setBreakOneLineHeadersMode( bool state ) {
    shouldBreakOneLineHeaders = state;
  }
  void ASFormatter::setBreakOneLineStatementsMode( bool state ) {
    shouldBreakOneLineStatements = state;
  }
  void ASFormatter::setCloseTemplatesMode( bool state ) {
    shouldCloseTemplates = state;
  }
  void ASFormatter::setTabSpaceConversionMode( bool state ) {
    shouldConvertTabs = state;
  }
  void ASFormatter::setIndentCol1CommentsMode( bool state ) {
    shouldIndentCol1Comments = state;
  }
  void ASFormatter::setBreakBlocksMode( bool state ) {
    shouldBreakBlocks = state;
  }
  void ASFormatter::setBreakClosingHeaderBlocksMode( bool state ) {
    shouldBreakClosingHeaderBlocks = state;
  }
  void ASFormatter::setDeleteEmptyLinesMode( bool state ) {
    shouldDeleteEmptyLines = state;
  }
  void ASFormatter::setPointerAlignment( PointerAlign alignment ) {
    pointerAlignment = alignment;
  }
  void ASFormatter::setReferenceAlignment( ReferenceAlign alignment ) {
    referenceAlignment = alignment;
  }
  void ASFormatter::goForward( int i ) {
    while( --i >= 0 ) {
      getNextChar();
    }
  }
  char ASFormatter::peekNextChar() const {
    char ch = ' ';
    size_t peekNum = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( peekNum == string::npos ) {
      return ch;
    }
    ch = currentLine[peekNum];
    return ch;
  }

  bool ASFormatter::isBeforeComment() const {
    bool foundComment = false;
    size_t peekNum = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( peekNum == string::npos ) {
      return foundComment;
    }
    foundComment = ( currentLine.compare( peekNum, 2, "/*" ) == 0 );
    return foundComment;
  }

  bool ASFormatter::isBeforeAnyComment() const {
    bool foundComment = false;
    size_t peekNum = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( peekNum == string::npos ) {
      return foundComment;
    }
    foundComment = ( currentLine.compare( peekNum, 2, "/*" ) == 0
                     || currentLine.compare( peekNum, 2, "//" ) == 0 );
    return foundComment;
  }

  bool ASFormatter::isBeforeAnyLineEndComment( int startPos ) const {
    bool foundLineEndComment = false;
    size_t peekNum = currentLine.find_first_not_of( " \t", startPos + 1 );
    if( peekNum != string::npos ) {
      if( currentLine.compare( peekNum, 2, "/*" ) == 0 ) {
        size_t endNum = currentLine.find( "*/", peekNum + 2 );
        if( endNum != string::npos ) {
          size_t nextChar = currentLine.find_first_not_of( " \t", endNum + 2 );
          if( nextChar == string::npos ) {
            foundLineEndComment = true;
          }
        }
      }
    }
    return foundLineEndComment;
  }
  bool ASFormatter::isBeforeMultipleLineEndComments( int startPos ) const {
    bool foundMultipleLineEndComment = false;
    size_t peekNum = currentLine.find_first_not_of( " \t", startPos + 1 );
    if( peekNum != string::npos ) {
      if( currentLine.compare( peekNum, 2, "/*" ) == 0 ) {
        size_t endNum = currentLine.find( "*/", peekNum + 2 );
        if( endNum != string::npos ) {
          size_t nextChar = currentLine.find_first_not_of( " \t", endNum + 2 );
          if( nextChar != string::npos
              && currentLine.compare( nextChar, 2, "//" ) == 0 ) {
            foundMultipleLineEndComment = true;
          }
        }
      }
    }
    return foundMultipleLineEndComment;
  }


  bool ASFormatter::getNextChar() {
    isInLineBreak = false;
    previousChar = currentChar;
    if( !isWhiteSpace( currentChar ) ) {
      previousNonWSChar = currentChar;
      if( !isInComment && !isInLineComment && !isInQuote
          && !isImmediatelyPostComment
          && !isImmediatelyPostLineComment
          && !isInPreprocessor
          && !isSequenceReached( "/*" )
          && !isSequenceReached( "//" ) ) {
        previousCommandChar = currentChar;
      }
    }
    if( charNum + 1 < ( int ) currentLine.length()
        && ( !isWhiteSpace( peekNextChar() ) || isInComment || isInLineComment ) ) {
      currentChar = currentLine[++charNum];
      if( currentChar == '\t' && shouldConvertTabs ) {
        convertTabToSpaces();
      }
      return true;
    }
    return getNextLine();
  }

  bool ASFormatter::getNextLine( bool emptyLineWasDeleted ) {
    if( !sourceIterator->hasMoreLines() ) {
      endOfCodeReached = true;
      return false;
    }
    if( appendOpeningBrace ) {
      currentLine = "{";
    } else {
      currentLine = sourceIterator->nextLine( emptyLineWasDeleted );
      assert( computeChecksumIn( currentLine ) );
    }
    inLineNumber++;
    if( endOfAsmReached ) {
      endOfAsmReached = isInAsmBlock = isInAsm = false;
    }
    shouldKeepLineUnbroken = false;
    isInCommentStartLine = false;
    isInCase = false;
    isInAsmOneLine = false;
    isHeaderInMultiStatementLine = false;
    isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar;
    haveLineContinuationChar = false;
    isImmediatelyPostEmptyLine = lineIsEmpty;
    previousChar = ' ';
    if( currentLine.length() == 0 ) {
      currentLine = string( " " );
    }
    if( !isVirgin ) {
      isInLineBreak = true;
    } else
    { isVirgin = false; }
    if( isImmediatelyPostNonInStmt ) {
      isCharImmediatelyPostNonInStmt = true;
      isImmediatelyPostNonInStmt = false;
    }
    isImmediatelyPostPreprocessor = isInPreprocessor;
    if( !isInComment
        && ( previousNonWSChar != '\\'
             || isEmptyLine( currentLine ) ) ) {
      isInPreprocessor = false;
    }
    if( passedSemicolon ) {
      isInExecSQL = false;
    }
    initNewLine();
    currentChar = currentLine[charNum];
    if( isInBraceRunIn && previousNonWSChar == '{' && !isInComment ) {
      isInLineBreak = false;
    }
    isInBraceRunIn = false;
    if( currentChar == '\t' && shouldConvertTabs ) {
      convertTabToSpaces();
    }
    if( shouldDeleteEmptyLines
        && lineIsEmpty
        && isBraceType( ( *braceTypeStack )[braceTypeStack->size() - 1], COMMAND_TYPE ) ) {
      if( !shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows() ) {
        isInPreprocessor = isImmediatelyPostPreprocessor;
        lineIsEmpty = false;
        return getNextLine( true );
      }
    }
    return true;
  }

  void ASFormatter::initNewLine() {
    size_t len = currentLine.length();
    size_t tabSize = getTabLength();
    charNum = 0;
    if( isInQuoteContinuation
        || ( isInPreprocessor && !getPreprocDefineIndent() ) ) {
      return;
    }
    if( isInExecSQL ) {
      size_t tabCount_ = 0;
      size_t i;
      for( i = 0; i < currentLine.length(); i++ ) {
        if( !isWhiteSpace( currentLine[i] ) ) {
          break;
        }
        if( currentLine[i] == '\t' ) {
          size_t numSpaces = tabSize - ( ( tabCount_ + i ) % tabSize );
          currentLine.replace( i, 1, numSpaces, ' ' );
          tabCount_++;
          i += tabSize - 1;
        }
      }
      trimContinuationLine();
      return;
    }
    if( isInComment ) {
      if( noTrimCommentContinuation ) {
        leadingSpaces = tabIncrementIn = 0;
      }
      trimContinuationLine();
      return;
    }
    isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly;
    lineIsCommentOnly = false;
    lineIsLineCommentOnly = false;
    lineEndsInCommentOnly = false;
    doesLineStartComment = false;
    currentLineBeginsWithBrace = false;
    lineIsEmpty = false;
    currentLineFirstBraceNum = string::npos;
    tabIncrementIn = 0;
    for( charNum = 0; isWhiteSpace( currentLine[charNum] ) && charNum + 1 < ( int ) len; charNum++ ) {
      if( currentLine[charNum] == '\t' && !isInPreprocessor ) {
        tabIncrementIn += tabSize - 1 - ( ( tabIncrementIn + charNum ) % tabSize );
      }
    }
    leadingSpaces = charNum + tabIncrementIn;
    if( isSequenceReached( "/*" ) ) {
      doesLineStartComment = true;
      if( ( int ) currentLine.length() > charNum + 2
          && currentLine.find( "*/", charNum + 2 ) != string::npos ) {
        lineIsCommentOnly = true;
      }
    } else if( isSequenceReached( "//" ) ) {
      lineIsLineCommentOnly = true;
    } else if( isSequenceReached( "{" ) ) {
      currentLineBeginsWithBrace = true;
      currentLineFirstBraceNum = charNum;
      size_t firstText = currentLine.find_first_not_of( " \t", charNum + 1 );
      if( firstText != string::npos ) {
        if( currentLine.compare( firstText, 2, "//" ) == 0 ) {
          lineIsLineCommentOnly = true;
        } else if( currentLine.compare( firstText, 2, "/*" ) == 0
                   || isExecSQL( currentLine, firstText ) ) {
          size_t j;
          for( j = charNum + 1; j < firstText && isWhiteSpace( currentLine[j] ); j++ ) {
            if( currentLine[j] == '\t' )
            { tabIncrementIn += tabSize - 1 - ( ( tabIncrementIn + j ) % tabSize ); }
          }
          leadingSpaces = j + tabIncrementIn;
          if( currentLine.compare( firstText, 2, "/*" ) == 0 ) {
            doesLineStartComment = true;
          }
        }
      }
    } else if( isWhiteSpace( currentLine[charNum] ) && !( charNum + 1 < ( int ) currentLine.length() ) ) {
      lineIsEmpty = true;
    }
    if( isInPreprocessor ) {
      if( !doesLineStartComment ) {
        leadingSpaces = 0;
      }
      charNum = 0;
    }
  }

  void ASFormatter::appendChar( char ch, bool canBreakLine ) {
    if( canBreakLine && isInLineBreak ) {  // *************新行
      breakLine();
    }
    formattedLine.append( 1, ch );
    isImmediatelyPostCommentOnly = false;
    if( maxCodeLength != string::npos ) {
      if( isOkToSplitFormattedLine() ) {
        updateFormattedLineSplitPoints( ch );
      }
      if( formattedLine.length() > maxCodeLength ) {
        testForTimeToSplitFormattedLine();
      }
    }
  }

  void ASFormatter::appendSequence( const string & sequence, bool canBreakLine ) {
    if( canBreakLine && isInLineBreak ) {  // *************新行
      breakLine();
    }
    formattedLine.append( sequence );
    if( formattedLine.length() > maxCodeLength ) {
      testForTimeToSplitFormattedLine();
    }
  }

  void ASFormatter::appendOperator( const string & sequence, bool canBreakLine ) {
    if( canBreakLine && isInLineBreak ) {  // *************新行
      breakLine();
    }
    formattedLine.append( sequence );
    if( maxCodeLength != string::npos ) {
      if( isOkToSplitFormattedLine() ) {
        updateFormattedLineSplitPointsOperator( sequence );
      }
      if( formattedLine.length() > maxCodeLength ) {
        testForTimeToSplitFormattedLine();
      }
    }
  }

  void ASFormatter::appendSpacePad() {  //附加空格键
    int len = formattedLine.length();
    if( len > 0 && !isWhiteSpace( formattedLine[len - 1] ) ) {
      formattedLine.append( 1, ' ' );
      spacePadNum++;
      if( maxCodeLength != string::npos ) {
        if( isOkToSplitFormattedLine() ) {
          updateFormattedLineSplitPoints( ' ' );
        }
        if( formattedLine.length() > maxCodeLength ) {
          testForTimeToSplitFormattedLine();
        }
      }
    }
  }

  void ASFormatter::appendSpaceAfter() {  // 在后面附加空格
    int len = currentLine.length();
    if( charNum + 1 < len && !isWhiteSpace( currentLine[charNum + 1] ) ) {
      formattedLine.append( 1, ' ' );
      spacePadNum++;
      if( maxCodeLength != string::npos ) {
        if( isOkToSplitFormattedLine() ) {
          updateFormattedLineSplitPoints( ' ' );
        }
        if( formattedLine.length() > maxCodeLength ) {
          testForTimeToSplitFormattedLine();
        }
      }
    }
  }

  void ASFormatter::breakLine( bool isSplitLine ) {
    isLineReady = true;
    isInLineBreak = false;
    spacePadNum = nextLineSpacePadNum;
    nextLineSpacePadNum = 0;
    readyFormattedLine = formattedLine;
    formattedLine.erase();
    prependEmptyLine = isPrependPostBlockEmptyLineRequested;
    if( !isSplitLine ) {
      formattedLineCommentNum = string::npos;
      clearFormattedLineSplitPoints();
      if( isAppendPostBlockEmptyLineRequested ) {
        isAppendPostBlockEmptyLineRequested = false;
        isPrependPostBlockEmptyLineRequested = true;
      } else {
        isPrependPostBlockEmptyLineRequested = false;
      }
    }
  }

  BraceType ASFormatter::getBraceType() {
    assert( currentChar == '{' );
    BraceType returnVal = NULL_TYPE;
    if( ( previousNonWSChar == '='
          || isBraceType( braceTypeStack->back(), ARRAY_TYPE ) )
        && previousCommandChar != ')'
        && !isNonParenHeader ) {
      returnVal = ARRAY_TYPE;
    } else if( foundPreDefinitionHeader && previousCommandChar != ')' ) {
      returnVal = DEFINITION_TYPE;
      if( foundNamespaceHeader ) {
        returnVal = ( BraceType )( returnVal | NAMESPACE_TYPE );
      } else if( foundClassHeader ) {
        returnVal = ( BraceType )( returnVal | CLASS_TYPE );
      } else if( foundStructHeader ) {
        returnVal = ( BraceType )( returnVal | STRUCT_TYPE );
      } else if( foundInterfaceHeader ) {
        returnVal = ( BraceType )( returnVal | INTERFACE_TYPE );
      }
    } else if( isInEnum ) {
      returnVal = ( BraceType )( ARRAY_TYPE | ENUM_TYPE );
    } else {
      bool isCommandType = ( foundPreCommandHeader
                             || foundPreCommandMacro
                             || ( currentHeader != nullptr && isNonParenHeader )
                             || ( previousCommandChar == ')' )
                             || ( previousCommandChar == ':' && !foundQuestionMark )
                             || ( previousCommandChar == ';' )
                             || ( ( previousCommandChar == '{' || previousCommandChar == '}' )
                                  && isPreviousBraceBlockRelated )
                             || ( isInClassInitializer
                                  && ( !isLegalNameChar( previousNonWSChar ) || foundPreCommandHeader ) )
                             || foundTrailingReturnType
                             || isInObjCMethodDefinition
                             || isInObjCInterface
                             || isJavaStaticConstructor
                             || isSharpDelegate );
      if( !isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader( charNum + 1 ) ) {
        isCommandType = true;
        isSharpAccessor = true;
      }
      if( isInExternC ) {
        returnVal = ( isCommandType ? COMMAND_TYPE : EXTERN_TYPE );
      } else
      { returnVal = ( isCommandType ? COMMAND_TYPE : ARRAY_TYPE ); }
    }
    int foundOneLineBlock = isOneLineBlockReached( currentLine, charNum );
    if( foundOneLineBlock == 2 && returnVal == COMMAND_TYPE ) {
      returnVal = ARRAY_TYPE;
    }
    if( foundOneLineBlock > 0 ) {
      returnVal = ( BraceType )( returnVal | SINGLE_LINE_TYPE );
      if( breakCurrentOneLineBlock ) {
        returnVal = ( BraceType )( returnVal | BREAK_BLOCK_TYPE );
      }
      if( foundOneLineBlock == 3 ) {
        returnVal = ( BraceType )( returnVal | EMPTY_BLOCK_TYPE );
      }
    }
    if( isBraceType( returnVal, ARRAY_TYPE ) ) {
      if( isNonInStatementArrayBrace() ) {
        returnVal = ( BraceType )( returnVal | ARRAY_NIS_TYPE );
        isNonInStatementArray = true;
        isImmediatelyPostNonInStmt = false;
        nonInStatementBrace = formattedLine.length() - 1;
      }
      if( isUniformInitializerBrace() ) {
        returnVal = ( BraceType )( returnVal | INIT_TYPE );
      }
    }
    return returnVal;
  }
  bool ASFormatter::isClassInitializer() const {
    assert( currentChar == ':' );
    assert( previousChar != ':' && peekNextChar() != ':' );
    bool foundClassInitializer = false;
    if( foundQuestionMark ) {
    } else if( parenStack->back() > 0 ) {
    } else if( isInEnum ) {
    } else if( isCStyle()
               && !isInCase
               && ( previousCommandChar == ')' || foundPreCommandHeader ) ) {
      foundClassInitializer = true;
    }
    return foundClassInitializer;
  }
  bool ASFormatter::isEmptyLine( const string & line ) const {
    return line.find_first_not_of( " \t" ) == string::npos;
  }
  bool ASFormatter::isExternC() const {
    assert( !isWhiteSpace( currentLine[charNum] ) );
    size_t startQuote = currentLine.find_first_of( " \t\"", charNum );
    if( startQuote == string::npos ) {
      return false;
    }
    startQuote = currentLine.find_first_not_of( " \t", startQuote );
    if( startQuote == string::npos ) {
      return false;
    }
    if( currentLine.compare( startQuote, 3, "\"C\"" ) != 0 ) {
      return false;
    }
    return true;
  }
  bool ASFormatter::isPointerOrReference() const {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    if( isJavaStyle() ) {
      return false;
    }
    if( isCharImmediatelyPostOperator ) {
      return false;
    }
    string lastWord = getPreviousWord( currentLine, charNum );
    if( lastWord.empty() ) {
      lastWord = " ";
    }
    string nextText = peekNextText( currentLine.substr( charNum + 1 ) );
    if( nextText.length() == 0 ) {
      nextText = " ";
    }
    char nextChar = nextText[0];
    if( isDigit( lastWord[0] )
        || isDigit( nextChar )
        || nextChar == '!'
        || nextChar == '~' ) {
      return false;
    }
    if( currentChar == '*'
        && charNum < ( int ) currentLine.length() - 1
        && isWhiteSpace( currentLine[charNum + 1] )
        && nextChar == '*' ) {
      return false;
    }
    if( ( foundCastOperator && nextChar == '>' )
        || isPointerOrReferenceVariable( lastWord ) ) {
      return true;
    }
    if( isInClassInitializer
        && previousNonWSChar != '('
        && previousNonWSChar != '{'
        && previousCommandChar != ','
        && nextChar != ')'
        && nextChar != '}' ) {
      return false;
    }
    if( currentChar == '&' && nextChar == '&' ) {
      if( previousNonWSChar == '>' ) {
        return true;
      }
      string followingText;
      if( ( int ) currentLine.length() > charNum + 2 ) {
        followingText = peekNextText( currentLine.substr( charNum + 2 ) );
      }
      if( followingText.length() > 0 && followingText[0] == ')' ) {
        return true;
      }
      if( currentHeader != nullptr || isInPotentialCalculation ) {
        return false;
      }
      if( parenStack->back() > 0 && isBraceType( braceTypeStack->back(), COMMAND_TYPE ) ) {
        return false;
      }
      return true;
    }
    if( nextChar == '*'
        || previousNonWSChar == '='
        || previousNonWSChar == '('
        || previousNonWSChar == '['
        || isCharImmediatelyPostReturn
        || isInTemplate
        || isCharImmediatelyPostTemplate
        || currentHeader == &AS_CATCH
        || currentHeader == &AS_FOREACH
        || currentHeader == &AS_QFOREACH ) {
      return true;
    }
    if( isBraceType( braceTypeStack->back(), ARRAY_TYPE )
        && isLegalNameChar( lastWord[0] )
        && isLegalNameChar( nextChar )
        && previousNonWSChar != ')' ) {
      if( isArrayOperator() ) {
        return false;
      }
    }
    if( parenStack->back() > 0
        && isLegalNameChar( lastWord[0] )
        && isLegalNameChar( nextChar ) ) {
      const string* followingOperator = getFollowingOperator();
      if( followingOperator != nullptr
          && followingOperator != &AS_MULT
          && followingOperator != &AS_BIT_AND ) {
        if( followingOperator == &AS_ASSIGN || followingOperator == &AS_COLON ) {
          return true;
        }
        return false;
      }
      if( isBraceType( braceTypeStack->back(), COMMAND_TYPE )
          || squareBracketCount > 0 ) {
        return false;
      }
      return true;
    }
    if( parenStack->back() > 0
        && nextChar == '('
        && previousNonWSChar != ','
        && previousNonWSChar != '('
        && previousNonWSChar != '!'
        && previousNonWSChar != '&'
        && previousNonWSChar != '*'
        && previousNonWSChar != '|' ) {
      return false;
    }
    if( nextChar == '-'
        || nextChar == '+' ) {
      size_t nextNum = currentLine.find_first_not_of( " \t", charNum + 1 );
      if( nextNum != string::npos ) {
        if( currentLine.compare( nextNum, 2, "++" ) != 0
            && currentLine.compare( nextNum, 2, "--" ) != 0 ) {
          return false;
        }
      }
    }
    bool isPR = ( !isInPotentialCalculation
                  || ( !isLegalNameChar( previousNonWSChar )
                       && !( previousNonWSChar == ')' && nextChar == '(' )
                       && !( previousNonWSChar == ')' && currentChar == '*' && !isImmediatelyPostCast() )
                       && previousNonWSChar != ']' )
                  || ( !isWhiteSpace( nextChar )
                       && nextChar != '-'
                       && nextChar != '('
                       && nextChar != '['
                       && !isLegalNameChar( nextChar ) )
                );
    return isPR;
  }
  bool ASFormatter::isDereferenceOrAddressOf() const {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    if( isCharImmediatelyPostTemplate ) {
      return false;
    }
    if( previousNonWSChar == '='
        || previousNonWSChar == ','
        || previousNonWSChar == '.'
        || previousNonWSChar == '{'
        || previousNonWSChar == '>'
        || previousNonWSChar == '<'
        || previousNonWSChar == '?'
        || isCharImmediatelyPostLineComment
        || isCharImmediatelyPostComment
        || isCharImmediatelyPostReturn ) {
      return true;
    }
    char nextChar = peekNextChar();
    if( currentChar == '*' && nextChar == '*' ) {
      if( previousNonWSChar == '(' ) {
        return true;
      }
      if( ( int ) currentLine.length() < charNum + 2 ) {
        return true;
      }
      return false;
    }
    if( currentChar == '&' && nextChar == '&' ) {
      if( previousNonWSChar == '(' || isInTemplate ) {
        return true;
      }
      if( ( int ) currentLine.length() < charNum + 2 ) {
        return true;
      }
      return false;
    }
    if( charNum == ( int ) currentLine.find_first_not_of( " \t" )
        && ( isBraceType( braceTypeStack->back(), COMMAND_TYPE )
             || parenStack->back() != 0 ) ) {
      return true;
    }
    string nextText = peekNextText( currentLine.substr( charNum + 1 ) );
    if( nextText.length() > 0 ) {
      if( nextText[0] == ')' || nextText[0] == '>'
          || nextText[0] == ',' || nextText[0] == '=' ) {
        return false;
      }
      if( nextText[0] == ';' ) {
        return true;
      }
    }
    if( ( currentChar == '*' && nextChar == '&' )
        || ( previousNonWSChar == '*' && currentChar == '&' ) ) {
      return false;
    }
    if( !isBraceType( braceTypeStack->back(), COMMAND_TYPE )
        && parenStack->back() == 0 ) {
      return false;
    }
    string lastWord = getPreviousWord( currentLine, charNum );
    if( lastWord == "else" || lastWord == "delete" ) {
      return true;
    }
    if( isPointerOrReferenceVariable( lastWord ) ) {
      return false;
    }
    bool isDA = ( !( isLegalNameChar( previousNonWSChar ) || previousNonWSChar == '>' )
                  || ( nextText.length() > 0 && !isLegalNameChar( nextText[0] ) && nextText[0] != '/' )
                  || ( ispunct( ( unsigned char )previousNonWSChar ) && previousNonWSChar != '.' )
                  || isCharImmediatelyPostReturn );
    return isDA;
  }
  bool ASFormatter::isPointerOrReferenceCentered() const {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    int prNum = charNum;
    int lineLength = ( int ) currentLine.length();
    if( peekNextChar() == ' ' ) {
      return false;
    }
    if( prNum < 1
        || currentLine[prNum - 1] != ' ' ) {
      return false;
    }
    if( prNum < 2
        || currentLine[prNum - 2] == ' ' ) {
      return false;
    }
    if( prNum + 1 < lineLength
        && ( currentLine[prNum + 1] == '*' || currentLine[prNum + 1] == '&' ) ) {
      prNum++;
    }
    if( prNum + 1 <= lineLength
        && currentLine[prNum + 1] != ' ' ) {
      return false;
    }
    if( prNum + 2 < lineLength
        && currentLine[prNum + 2] == ' ' ) {
      return false;
    }
    return true;
  }
  bool ASFormatter::isPointerOrReferenceVariable( const string & word ) const {
    return ( word == "char"
             || word == "int"
             || word == "void"
             || ( word.length() >= 6
                  && word.compare( word.length() - 2, 2, "_t" ) == 0 )
             || word == "INT"
             || word == "VOID" );
  }
  bool ASFormatter::isUnaryOperator() const {
    assert( currentChar == '+' || currentChar == '-' );
    return ( ( isCharImmediatelyPostReturn || !isLegalNameChar( previousCommandChar ) )
             && previousCommandChar != '.'
             && previousCommandChar != '\"'
             && previousCommandChar != '\''
             && previousCommandChar != ')'
             && previousCommandChar != ']' );
  }
  bool ASFormatter::isInSwitchStatement() const {
    assert( isInLineComment || isInComment );
    if( !preBraceHeaderStack->empty() )
      for( size_t i = 1; i < preBraceHeaderStack->size(); i++ )
        if( preBraceHeaderStack->at( i ) == &AS_SWITCH ) {
          return true;
        }
    return false;
  }
  bool ASFormatter::isInExponent() const {
    assert( currentChar == '+' || currentChar == '-' );
    if( charNum >= 2 ) {
      char prevPrevFormattedChar = currentLine[charNum - 2];
      char prevFormattedChar = currentLine[charNum - 1];
      return ( ( prevFormattedChar == 'e' || prevFormattedChar == 'E' )
               && ( prevPrevFormattedChar == '.' || isDigit( prevPrevFormattedChar ) ) );
    }
    return false;
  }
  bool ASFormatter::isNonInStatementArrayBrace() const {
    bool returnVal = false;
    char nextChar = peekNextChar();
    if( currentLineBeginsWithBrace
        && charNum == ( int ) currentLineFirstBraceNum
        && nextChar != '}' ) {
      returnVal = true;
    }
    if( isWhiteSpace( nextChar )
        || isBeforeAnyLineEndComment( charNum )
        || nextChar == '{' ) {
      returnVal = true;
    }
    if( isJavaStyle() && previousNonWSChar == ']' ) {
      returnVal = false;
    }
    return returnVal;
  }
  int ASFormatter::isOneLineBlockReached( const string & line, int startChar ) const {
    assert( line[startChar] == '{' );
    bool isInComment_ = false;
    bool isInQuote_ = false;
    bool hasText = false;
    int braceCount = 0;
    int lineLength = line.length();
    char quoteChar_ = ' ';
    char ch = ' ';
    char prevCh = ' ';
    for( int i = startChar; i < lineLength; ++i ) {
      ch = line[i];
      if( isInComment_ ) {
        if( line.compare( i, 2, "*/" ) == 0 ) {
          isInComment_ = false;
          ++i;
        }
        continue;
      }
      if( ch == '\\' ) {
        ++i;
        continue;
      }
      if( isInQuote_ ) {
        if( ch == quoteChar_ ) {
          isInQuote_ = false;
        }
        continue;
      }
      if( ch == '"'
          || ( ch == '\'' && !isDigitSeparator( line, i ) ) ) {
        isInQuote_ = true;
        quoteChar_ = ch;
        continue;
      }
      if( line.compare( i, 2, "//" ) == 0 ) {
        break;
      }
      if( line.compare( i, 2, "/*" ) == 0 ) {
        isInComment_ = true;
        ++i;
        continue;
      }
      if( ch == '{' ) {
        ++braceCount;
        continue;
      }
      if( ch == '}' ) {
        --braceCount;
        if( braceCount == 0 ) {
          if( parenStack->back() == 0 && prevCh != '}' ) {
            size_t peekNum = line.find_first_not_of( " \t", i + 1 );
            if( peekNum != string::npos && line[peekNum] == ',' )
            { return 2; }
          }
          if( !hasText ) {
            return 3;
          }
          return 1;
        }
      }
      if( ch == ';' ) {
        continue;
      }
      if( !isWhiteSpace( ch ) ) {
        hasText = true;
        prevCh = ch;
      }
    }
    return 0;
  }

  bool ASFormatter::isNextWordSharpNonParenHeader( int startChar ) const {
    string nextText = peekNextText( currentLine.substr( startChar ) );
    if( nextText.length() == 0 ) {
      return false;
    }
    if( nextText[0] == '[' ) {
      return true;
    }
    if( !isCharPotentialHeader( nextText, 0 ) ) {
      return false;
    }
    if( findKeyword( nextText, 0, AS_GET ) || findKeyword( nextText, 0, AS_SET )
        || findKeyword( nextText, 0, AS_ADD ) || findKeyword( nextText, 0, AS_REMOVE ) ) {
      return true;
    }
    return false;
  }

  bool ASFormatter::isNextCharOpeningBrace( int startChar )
  const {
    bool retVal = false;
    string nextText = peekNextText( currentLine.substr( startChar ) );
    if( nextText.length() > 0 && nextText.compare( 0, 1, "{" ) == 0 ) {
      retVal = true;
    }
    return retVal;
  }

  bool ASFormatter::isOperatorPaddingDisabled() const {
    size_t commentStart = currentLine.find( "//", charNum );
    if( commentStart == string::npos ) {
      commentStart = currentLine.find( "/*", charNum );
      if( commentStart != string::npos ) {
        size_t commentEnd = currentLine.find( "*/", commentStart + 2 );
        if( commentEnd == string::npos ) {
          commentStart = string::npos;
        }
      }
    }
    if( commentStart == string::npos ) {
      return false;
    }
    size_t noPadStart = currentLine.find( "*NOPAD*", commentStart );
    if( noPadStart == string::npos ) {
      return false;
    }
    return true;
  }

  bool ASFormatter::isUniformInitializerBrace() const {
    if( isCStyle() && !isInEnum && !isImmediatelyPostPreprocessor ) {
      if( isInClassInitializer
          || isLegalNameChar( previousNonWSChar ) ) {
        return true;
      }
    }
    return false;
  }

  bool ASFormatter::isMultiStatementLine() const {
    assert( ( isImmediatelyPostHeader || foundClosingHeader ) );
    bool isInComment_ = false;
    bool isInQuote_ = false;
    int  semiCount_ = 0;
    int  parenCount_ = 0;
    int  braceCount_ = 0;
    for( size_t i = 0; i < currentLine.length(); i++ ) {
      if( isInComment_ ) {
        if( currentLine.compare( i, 2, "*/" ) == 0 ) {
          isInComment_ = false;
          continue;
        }
      }
      if( currentLine.compare( i, 2, "/*" ) == 0 ) {
        isInComment_ = true;
        continue;
      }
      if( currentLine.compare( i, 2, "//" ) == 0 ) {
        return false;
      }
      if( isInQuote_ ) {
        if( currentLine[i] == '"' || currentLine[i] == '\'' ) {
          isInQuote_ = false;
        }
        continue;
      }
      if( currentLine[i] == '"' || currentLine[i] == '\'' ) {
        isInQuote_ = true;
        continue;
      }
      if( currentLine[i] == '(' ) {
        ++parenCount_;
        continue;
      }
      if( currentLine[i] == ')' ) {
        --parenCount_;
        continue;
      }
      if( parenCount_ > 0 ) {
        continue;
      }
      if( currentLine[i] == '{' ) {
        ++braceCount_;
      }
      if( currentLine[i] == '}' ) {
        --braceCount_;
      }
      if( braceCount_ > 0 ) {
        continue;
      }
      if( currentLine[i] == ';' ) {
        ++semiCount_;
        if( semiCount_ > 1 ) {
          return true;
        }
        continue;
      }
    }
    return false;
  }

  string ASFormatter::peekNextText( const string& firstLine, bool endOnEmptyLine,
                                    shared_ptr<ASPeekStream> streamArg ) const {
    bool isFirstLine = true;
    string nextLine_ = firstLine;
    size_t firstChar = string::npos;
    shared_ptr<ASPeekStream>
    stream = streamArg;
    if( stream == nullptr ) {
      stream = make_shared<ASPeekStream>( sourceIterator );
    }
    bool isInComment_ = false;
    while( stream->hasMoreLines() || isFirstLine ) {
      if( isFirstLine ) {
        isFirstLine = false;
      } else
      { nextLine_ = stream->peekNextLine(); }
      firstChar = nextLine_.find_first_not_of( " \t" );
      if( firstChar == string::npos ) {
        if( endOnEmptyLine && !isInComment_ ) {
          break;
        }
        continue;
      }
      if( nextLine_.compare( firstChar, 2, "/*" ) == 0 ) {
        firstChar += 2;
        isInComment_ = true;
      }
      if( isInComment_ ) {
        firstChar = nextLine_.find( "*/", firstChar );
        if( firstChar == string::npos ) {
          continue;
        }
        firstChar += 2;
        isInComment_ = false;
        firstChar = nextLine_.find_first_not_of( " \t", firstChar );
        if( firstChar == string::npos ) {
          continue;
        }
      }
      if( nextLine_.compare( firstChar, 2, "//" ) == 0 ) {
        continue;
      }
      break;
    }
    if( firstChar == string::npos ) {
      nextLine_ = "";
    } else
    { nextLine_ = nextLine_.substr( firstChar ); }
    return nextLine_;
  }

  void ASFormatter::adjustComments() {
    assert( spacePadNum != 0 );
    assert( isSequenceReached( "//" ) || isSequenceReached( "/*" ) );
    if( isSequenceReached( "/*" ) ) {
      size_t endNum = currentLine.find( "*/", charNum + 2 );
      if( endNum == string::npos ) {
        return;
      }
      if( currentLine.find_first_not_of( " \t", endNum + 2 ) != string::npos ) {
        return;
      }
    }
    size_t len = formattedLine.length();
    if( formattedLine[len - 1] == '\t' ) {
      return;
    }
    if( spacePadNum < 0 ) {
      int adjust = -spacePadNum;
      formattedLine.append( adjust, ' ' );
    } else if( spacePadNum > 0 ) {
      int adjust = spacePadNum;
      size_t lastText = formattedLine.find_last_not_of( ' ' );
      if( lastText != string::npos
          && lastText < len - adjust - 1 ) {
        formattedLine.resize( len - adjust );
      } else if( len > lastText + 2 ) {
        formattedLine.resize( lastText + 2 );
      } else if( len < lastText + 2 ) {
        formattedLine.append( len - lastText, ' ' );
      }
    }
  }

  void ASFormatter::appendCharInsideComments() {
    if( formattedLineCommentNum == string::npos
        || formattedLineCommentNum == 0 ) {
      appendCurrentChar();
      return;
    }
    assert( formattedLine.compare( formattedLineCommentNum, 2, "//" ) == 0
            || formattedLine.compare( formattedLineCommentNum, 2, "/*" ) == 0 );
    size_t end = formattedLineCommentNum;
    size_t beg = formattedLine.find_last_not_of( " \t", end - 1 );
    if( beg == string::npos ) {
      appendCurrentChar();
      return;
    }
    beg++;
    if( end - beg < 3 ) {
      formattedLine.insert( beg, 3 - end + beg, ' ' );
    }
    if( formattedLine[beg] == '\t' ) {
      formattedLine.insert( beg, 1, ' ' );
    }
    formattedLine[beg + 1] = currentChar;
    testForTimeToSplitFormattedLine();
    if( isBeforeComment() ) {
      breakLine();
    } else if( isCharImmediatelyPostLineComment ) {
      shouldBreakLineAtNextChar = true;
    }
  }

  void ASFormatter::padOperators( const string* newOperator ) {
    assert( shouldPadOperators );
    assert( newOperator != nullptr );
    char nextNonWSChar = ASBase::peekNextChar( currentLine, charNum );
    bool shouldPad = ( newOperator != &AS_SCOPE_RESOLUTION
                       && newOperator != &AS_PLUS_PLUS
                       && newOperator != &AS_MINUS_MINUS
                       && newOperator != &AS_NOT
                       && newOperator != &AS_BIT_NOT
                       && newOperator != &AS_ARROW
                       && !( newOperator == &AS_COLON && !foundQuestionMark
                             && ( isInObjCMethodDefinition || isInObjCInterface
                                  || isInObjCSelector || squareBracketCount != 0 ) )
                       && !( newOperator == &AS_MINUS && isInExponent() )
                       && !( newOperator == &AS_PLUS && isInExponent() )
                       && !( ( newOperator == &AS_PLUS || newOperator == &AS_MINUS )
                             && ( previousNonWSChar == '('
                                  || previousNonWSChar == '['
                                  || previousNonWSChar == '='
                                  || previousNonWSChar == ','
                                  || previousNonWSChar == ':'
                                  || previousNonWSChar == '{' ) )
                       && !( newOperator == &AS_MULT
                             && ( previousNonWSChar == '.'
                                  || previousNonWSChar == '>' ) )
                       && !( newOperator == &AS_MULT && peekNextChar() == '>' )
                       && !( ( isInTemplate || isImmediatelyPostTemplate )
                             && ( newOperator == &AS_LS || newOperator == &AS_GR ) )
                       && !( newOperator == &AS_GCC_MIN_ASSIGN
                             && ASBase::peekNextChar( currentLine, charNum + 1 ) == '>' )
                       && !( newOperator == &AS_GR && previousNonWSChar == '?' )
                       && !( newOperator == &AS_QUESTION
                             && isJavaStyle()
                             && ( previousNonWSChar == '<'
                                  || nextNonWSChar == '>'
                                  || nextNonWSChar == '.' ) )
                       && !( newOperator == &AS_QUESTION
                             && isSharpStyle()
                             && ( nextNonWSChar == '.'
                                  || nextNonWSChar == '[' ) )
                       && !isCharImmediatelyPostOperator
                       && !isInCase
                       && !isInAsm
                       && !isInAsmOneLine
                       && !isInAsmBlock
                     );
    if( shouldPad
        && !( newOperator == &AS_COLON
              && ( !foundQuestionMark && !isInEnum ) && currentHeader != &AS_FOR )
        && !( newOperator == &AS_QUESTION && isSharpStyle()
              && currentLine.find( ':', charNum + 1 ) == string::npos )
      ) {
      appendSpacePad();
    }
    appendOperator( *newOperator );
    goForward( newOperator->length() - 1 );
    currentChar = ( *newOperator )[newOperator->length() - 1];
    if( shouldPad
        && !isBeforeAnyComment()
        && !( newOperator == &AS_PLUS && isUnaryOperator() )
        && !( newOperator == &AS_MINUS && isUnaryOperator() )
        && !( currentLine.compare( charNum + 1, 1, AS_SEMICOLON ) == 0 )
        && !( currentLine.compare( charNum + 1, 2, AS_SCOPE_RESOLUTION ) == 0 )
        && !( peekNextChar() == ',' )
        && !( newOperator == &AS_QUESTION && isSharpStyle()
              && peekNextChar() == '[' )
      ) {
      appendSpaceAfter();
    }
  }

  void ASFormatter::formatPointerOrReference() {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    assert( !isJavaStyle() );
    int pa = pointerAlignment;
    int ra = referenceAlignment;
    int itemAlignment = ( currentChar == '*' || currentChar == '^' ) ? pa : ( ( ra == REF_SAME_AS_PTR ) ? pa : ra );
    int ptrLength = 1;
    char peekedChar = peekNextChar();
    if( ( currentChar == '*' && peekedChar == '*' )
        || ( currentChar == '&' && peekedChar == '&' ) ) {
      ptrLength = 2;
      size_t nextChar = currentLine.find_first_not_of( " \t", charNum + 2 );
      if( nextChar == string::npos ) {
        peekedChar = ' ';
      } else
      { peekedChar = currentLine[nextChar]; }
    }
    if( peekedChar == ')' || peekedChar == '>' || peekedChar == ',' ) {
      formatPointerOrReferenceCast();
      return;
    }
    if( charNum > 0
        && !isWhiteSpace( currentLine[charNum - 1] )
        && formattedLine.length() > 0
        && isWhiteSpace( formattedLine[formattedLine.length() - 1] ) ) {
      formattedLine.erase( formattedLine.length() - 1 );
      spacePadNum--;
    }
    if( itemAlignment == PTR_ALIGN_TYPE ) {
      formatPointerOrReferenceToType();
    } else if( itemAlignment == PTR_ALIGN_MIDDLE ) {
      formatPointerOrReferenceToMiddle();
    } else if( itemAlignment == PTR_ALIGN_NAME ) {
      formatPointerOrReferenceToName();
    } else {
      formattedLine.append( ptrLength, currentChar );
      if( ptrLength > 1 ) {
        goForward( ptrLength - 1 );
      }
    }
  }

  void ASFormatter::formatPointerOrReferenceToType() {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    assert( !isJavaStyle() );
    bool isOldPRCentered = isPointerOrReferenceCentered();
    size_t prevCh = formattedLine.find_last_not_of( " \t" );
    if( prevCh == string::npos ) {
      prevCh = 0;
    }
    if( formattedLine.length() == 0 || prevCh == formattedLine.length() - 1 ) {
      formattedLine.append( 1, currentChar );
    } else {
      string charSave = formattedLine.substr( prevCh + 1, 1 );
      formattedLine[prevCh + 1] = currentChar;
      formattedLine.append( charSave );
    }
    if( isSequenceReached( "**" ) || isSequenceReached( "&&" ) ) {
      if( formattedLine.length() == 1 ) {
        formattedLine.append( 1, currentChar );
      } else
      { formattedLine.insert( prevCh + 2, 1, currentChar ); }
      goForward( 1 );
    }
    if( charNum < ( int ) currentLine.length() - 1
        && !isWhiteSpace( currentLine[charNum + 1] )
        && currentLine[charNum + 1] != ')' ) {
      appendSpacePad();
    }
    if( isOldPRCentered
        && isWhiteSpace( formattedLine[formattedLine.length() - 1] ) ) {
      formattedLine.erase( formattedLine.length() - 1, 1 );
      spacePadNum--;
    }
    if( maxCodeLength != string::npos ) {
      size_t index = formattedLine.length() - 1;
      if( isWhiteSpace( formattedLine[index] ) ) {
        updateFormattedLineSplitPointsPointerOrReference( index );
        testForTimeToSplitFormattedLine();
      }
    }
  }

  void ASFormatter::formatPointerOrReferenceToMiddle() {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    assert( !isJavaStyle() );
    size_t wsBefore = currentLine.find_last_not_of( " \t", charNum - 1 );
    if( wsBefore == string::npos ) {
      wsBefore = 0;
    } else
    { wsBefore = charNum - wsBefore - 1; }
    string sequenceToInsert( 1, currentChar );
    if( isSequenceReached( "**" ) ) {
      sequenceToInsert = "**";
      goForward( 1 );
    } else if( isSequenceReached( "&&" ) ) {
      sequenceToInsert = "&&";
      goForward( 1 );
    } else if( currentChar == '*' && peekNextChar() == '&'
               && ( referenceAlignment == REF_ALIGN_TYPE
                    || referenceAlignment == REF_ALIGN_MIDDLE
                    || referenceAlignment == REF_SAME_AS_PTR ) ) {
      sequenceToInsert = "*&";
      goForward( 1 );
      for( size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace( currentLine[i] ); i++ ) {
        goForward( 1 );
      }
    }
    if( isBeforeAnyComment() ) {
      appendSpacePad();
      formattedLine.append( sequenceToInsert );
      appendSpaceAfter();
      return;
    }
    bool isAfterScopeResolution = previousNonWSChar == ':';
    size_t charNumSave = charNum;
    if( currentLine.find_first_not_of( " \t", charNum + 1 ) == string::npos ) {
      if( wsBefore == 0 && !isAfterScopeResolution ) {
        formattedLine.append( 1, ' ' );
      }
      formattedLine.append( sequenceToInsert );
      return;
    }
    for( size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace( currentLine[i] ); i++ ) {
      goForward( 1 );
      if( formattedLine.length() > 0 ) {
        formattedLine.append( 1, currentLine[i] );
      } else
      { spacePadNum--; }
    }
    size_t wsAfter = currentLine.find_first_not_of( " \t", charNumSave + 1 );
    if( wsAfter == string::npos || isBeforeAnyComment() ) {
      wsAfter = 0;
    } else
    { wsAfter = wsAfter - charNumSave - 1; }
    if( isAfterScopeResolution ) {
      size_t lastText = formattedLine.find_last_not_of( " \t" );
      formattedLine.insert( lastText + 1, sequenceToInsert );
      appendSpacePad();
    } else if( formattedLine.length() > 0 ) {
      if( wsBefore + wsAfter < 2 ) {
        size_t charsToAppend = ( 2 - ( wsBefore + wsAfter ) );
        formattedLine.append( charsToAppend, ' ' );
        spacePadNum += charsToAppend;
        if( wsBefore == 0 ) {
          wsBefore++;
        }
        if( wsAfter == 0 ) {
          wsAfter++;
        }
      }
      size_t padAfter = ( wsBefore + wsAfter ) / 2;
      size_t index = formattedLine.length() - padAfter;
      formattedLine.insert( index, sequenceToInsert );
    } else {
      formattedLine.append( sequenceToInsert );
      if( wsAfter == 0 ) {
        wsAfter++;
      }
      formattedLine.append( wsAfter, ' ' );
      spacePadNum += wsAfter;
    }
    if( maxCodeLength != string::npos && formattedLine.length() > 0 ) {
      size_t index = formattedLine.find_last_not_of( " \t" );
      if( index != string::npos && ( index < formattedLine.length() - 1 ) ) {
        index++;
        updateFormattedLineSplitPointsPointerOrReference( index );
        testForTimeToSplitFormattedLine();
      }
    }
  }

  void ASFormatter::formatPointerOrReferenceToName() {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    assert( !isJavaStyle() );
    bool isOldPRCentered = isPointerOrReferenceCentered();
    size_t startNum = formattedLine.find_last_not_of( " \t" );
    if( startNum == string::npos ) {
      startNum = 0;
    }
    string sequenceToInsert( 1, currentChar );
    if( isSequenceReached( "**" ) ) {
      sequenceToInsert = "**";
      goForward( 1 );
    } else if( isSequenceReached( "&&" ) ) {
      sequenceToInsert = "&&";
      goForward( 1 );
    } else if( currentChar == '*' && peekNextChar() == '&' ) {
      sequenceToInsert = "*&";
      goForward( 1 );
      for( size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace( currentLine[i] ); i++ ) {
        goForward( 1 );
      }
    }
    char peekedChar = peekNextChar();
    bool isAfterScopeResolution = previousNonWSChar == ':';
    if( !isBeforeAnyComment()
        && ( int ) currentLine.find_first_not_of( " \t", charNum + 1 ) > charNum ) {
      for( size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace( currentLine[i] ); i++ ) {
        if( shouldPadParensOutside && peekedChar == '(' && !isOldPRCentered ) {
          size_t start = currentLine.find_first_not_of( "( \t", charNum + 1 );
          if( start != string::npos && currentLine[start] != ')' ) {
            break;
          }
        }
        goForward( 1 );
        if( formattedLine.length() > 0 ) {
          formattedLine.append( 1, currentLine[i] );
        } else
        { spacePadNum--; }
      }
    }
    if( isAfterScopeResolution ) {
      size_t lastText = formattedLine.find_last_not_of( " \t" );
      if( lastText != string::npos && lastText + 1 < formattedLine.length() ) {
        formattedLine.erase( lastText + 1 );
      }
    } else if( formattedLine.length() > 0
               && ( formattedLine.length() <= startNum + 1
                    || !isWhiteSpace( formattedLine[startNum + 1] ) ) ) {
      formattedLine.insert( startNum + 1, 1, ' ' );
      spacePadNum++;
    }
    appendSequence( sequenceToInsert, false );
    if( isOldPRCentered
        && formattedLine.length() > startNum + 1
        && isWhiteSpace( formattedLine[startNum + 1] )
        && !isBeforeAnyComment() ) {
      formattedLine.erase( startNum + 1, 1 );
      spacePadNum--;
    }
    if( peekedChar == '=' ) {
      appendSpaceAfter();
      if( formattedLine.length() > startNum
          && isWhiteSpace( formattedLine[startNum + 1] )
          && isWhiteSpace( formattedLine[startNum + 2] ) ) {
        formattedLine.erase( startNum + 1, 1 );
        spacePadNum--;
      }
    }
    if( maxCodeLength != string::npos ) {
      size_t index = formattedLine.find_last_of( " \t" );
      if( index != string::npos
          && index < formattedLine.length() - 1
          && ( formattedLine[index + 1] == '*'
               || formattedLine[index + 1] == '&'
               || formattedLine[index + 1] == '^' ) ) {
        updateFormattedLineSplitPointsPointerOrReference( index );
        testForTimeToSplitFormattedLine();
      }
    }
  }

  void ASFormatter::formatPointerOrReferenceCast() {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    assert( !isJavaStyle() );
    int pa = pointerAlignment;
    int ra = referenceAlignment;
    int itemAlignment = ( currentChar == '*' || currentChar == '^' ) ? pa : ( ( ra == REF_SAME_AS_PTR ) ? pa : ra );
    string sequenceToInsert( 1, currentChar );
    if( isSequenceReached( "**" ) || isSequenceReached( "&&" ) ) {
      goForward( 1 );
      sequenceToInsert.append( 1, currentLine[charNum] );
    }
    if( itemAlignment == PTR_ALIGN_NONE ) {
      appendSequence( sequenceToInsert, false );
      return;
    }
    char prevCh = ' ';
    size_t prevNum = formattedLine.find_last_not_of( " \t" );
    if( prevNum != string::npos ) {
      prevCh = formattedLine[prevNum];
      if( prevNum + 1 < formattedLine.length()
          && isWhiteSpace( formattedLine[prevNum + 1] )
          && prevCh != '(' ) {
        spacePadNum -= ( formattedLine.length() - 1 - prevNum );
        formattedLine.erase( prevNum + 1 );
      }
    }
    bool isAfterScopeResolution = previousNonWSChar == ':';
    if( ( itemAlignment == PTR_ALIGN_MIDDLE || itemAlignment == PTR_ALIGN_NAME )
        && !isAfterScopeResolution && prevCh != '(' ) {
      appendSpacePad();
      if( maxCodeLength != string::npos && formattedLine.length() > 0 ) {
        updateFormattedLineSplitPointsPointerOrReference( formattedLine.length() - 1 );
      }
      appendSequence( sequenceToInsert, false );
    } else
    { appendSequence( sequenceToInsert, false ); }
  }

  void ASFormatter::padParens() {
    assert( currentChar == '(' || currentChar == ')' );
    assert( shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen );
    int spacesOutsideToDelete = 0;
    int spacesInsideToDelete = 0;
    if( currentChar == '(' ) {
      spacesOutsideToDelete = formattedLine.length() - 1;
      spacesInsideToDelete = 0;
      if( shouldUnPadParens ) {
        char lastChar = ' ';
        bool prevIsParenHeader = false;
        size_t i = formattedLine.find_last_not_of( " \t" );
        if( i != string::npos ) {
          if( formattedLine[i] == '{' ) {
            spacesOutsideToDelete = 0;
          } else if( isCharImmediatelyPostPointerOrReference ) {
            spacesOutsideToDelete = 0;
          } else {
            spacesOutsideToDelete -= i;
            lastChar = formattedLine[i];
            string prevWord = getPreviousWord( formattedLine, formattedLine.length() );
            const string* prevWordH = nullptr;
            if( shouldPadHeader
                && prevWord.length() > 0
                && isCharPotentialHeader( prevWord, 0 ) )
            { prevWordH = ASBase::findHeader( prevWord, 0, headers ); }
            if( prevWordH != nullptr )
            { prevIsParenHeader = true; }
            else if( prevWord == AS_RETURN )
            { prevIsParenHeader = true; }
            else if( ( prevWord == AS_NEW || prevWord == AS_DELETE )
                     && shouldPadHeader )
            { prevIsParenHeader = true; }
            else if( isCStyle() && prevWord == AS_THROW && shouldPadHeader )
            { prevIsParenHeader = true; }
            else if( prevWord == "and" || prevWord == "or" || prevWord == "in" )
            { prevIsParenHeader = true; }
            else if( prevWord == "bool"
                     || prevWord == "int"
                     || prevWord == "void"
                     || prevWord == "void*"
                     || prevWord == "char"
                     || prevWord == "char*"
                     || prevWord == "long"
                     || prevWord == "double"
                     || prevWord == "float"
                     || ( prevWord.length() >= 4
                          && prevWord.compare( prevWord.length() - 2, 2, "_t" ) == 0 )
                     || prevWord == "Int32"
                     || prevWord == "UInt32"
                     || prevWord == "Int64"
                     || prevWord == "UInt64"
                     || prevWord == "BOOL"
                     || prevWord == "DWORD"
                     || prevWord == "HWND"
                     || prevWord == "INT"
                     || prevWord == "LPSTR"
                     || prevWord == "VOID"
                     || prevWord == "LPVOID"
                   )
            { prevIsParenHeader = true; }
          }
        }
        if( shouldPadParensOutside || prevIsParenHeader ) {
          spacesOutsideToDelete--;
        } else if( lastChar == '|'
                   || lastChar == '&'
                   || lastChar == ','
                   || ( lastChar == '(' && shouldPadParensInside )
                   || ( lastChar == '>' && !foundCastOperator )
                   || lastChar == '<'
                   || lastChar == '?'
                   || lastChar == ':'
                   || lastChar == ';'
                   || lastChar == '='
                   || lastChar == '+'
                   || lastChar == '-'
                   || lastChar == '*'
                   || lastChar == '/'
                   || lastChar == '%'
                   || lastChar == '^'
                 ) {
          spacesOutsideToDelete--;
        }
        if( spacesOutsideToDelete > 0 ) {
          formattedLine.erase( i + 1, spacesOutsideToDelete );
          spacePadNum -= spacesOutsideToDelete;
        }
      }
      char peekedCharOutside = peekNextChar();
      if( shouldPadFirstParen && previousChar != '(' && peekedCharOutside != ')' ) {
        appendSpacePad();
      } else if( shouldPadParensOutside ) {
        if( !( currentChar == '(' && peekedCharOutside == ')' ) ) {
          appendSpacePad();
        }
      }
      appendCurrentChar();
      if( shouldUnPadParens ) {
        size_t j = currentLine.find_first_not_of( " \t", charNum + 1 );
        if( j != string::npos ) {
          spacesInsideToDelete = j - charNum - 1;
        }
        if( shouldPadParensInside ) {
          spacesInsideToDelete--;
        }
        if( spacesInsideToDelete > 0 ) {
          currentLine.erase( charNum + 1, spacesInsideToDelete );
          spacePadNum -= spacesInsideToDelete;
        }
        if( shouldConvertTabs
            && ( int ) currentLine.length() > charNum + 1
            && currentLine[charNum + 1] == '\t' ) {
          currentLine[charNum + 1] = ' ';
        }
      }
      char peekedCharInside = peekNextChar();
      if( shouldPadParensInside )
        if( !( currentChar == '(' && peekedCharInside == ')' ) ) {
          appendSpaceAfter();
        }
    } else if( currentChar == ')' ) {
      if( shouldUnPadParens ) {
        spacesInsideToDelete = formattedLine.length();
        size_t i = formattedLine.find_last_not_of( " \t" );
        if( i != string::npos ) {
          spacesInsideToDelete = formattedLine.length() - 1 - i;
        }
        if( shouldPadParensInside ) {
          spacesInsideToDelete--;
        }
        if( spacesInsideToDelete > 0 ) {
          formattedLine.erase( i + 1, spacesInsideToDelete );
          spacePadNum -= spacesInsideToDelete;
        }
      }
      if( shouldPadParensInside )
        if( !( previousChar == '(' && currentChar == ')' ) ) {
          appendSpacePad();
        }
      appendCurrentChar();
      if( shouldUnPadParens ) {
      }
      char peekedCharOutside = peekNextChar();
      if( shouldPadParensOutside )
        if( peekedCharOutside != ';'
            && peekedCharOutside != ','
            && peekedCharOutside != '.'
            && peekedCharOutside != '+'
            && peekedCharOutside != '-'
            && peekedCharOutside != ']' ) {
          appendSpaceAfter();
        }
    }
  }

  void ASFormatter::padObjCMethodPrefix() {
    assert( currentChar == '(' && isImmediatelyPostObjCMethodPrefix );
    assert( shouldPadMethodPrefix || shouldUnPadMethodPrefix );
    size_t prefix = formattedLine.find_first_of( "+-" );
    if( prefix == string::npos ) {
      return;
    }
    size_t paren = formattedLine.find_first_of( '(' );
    if( paren == string::npos ) {
      return;
    }
    int spaces = paren - prefix - 1;
    if( shouldPadMethodPrefix ) {
      if( spaces == 0 ) {
        formattedLine.insert( prefix + 1, 1, ' ' );
        spacePadNum += 1;
      } else if( spaces > 1 ) {
        formattedLine.erase( prefix + 1, spaces - 1 );
        spacePadNum -= spaces - 1;
      }
    } else if( shouldUnPadMethodPrefix ) {
      if( spaces > 0 ) {
        formattedLine.erase( prefix + 1, spaces );
        spacePadNum -= spaces;
      }
    }
  }

  void ASFormatter::padObjCReturnType() {
    assert( currentChar == ')' && isInObjCReturnType );
    assert( shouldPadReturnType || shouldUnPadReturnType );
    size_t nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( nextText == string::npos ) {
      return;
    }
    int spaces = nextText - charNum - 1;
    if( shouldPadReturnType ) {
      if( spaces == 0 ) {
        if( formattedLine[formattedLine.length() - 1] != ' ' ) {
          formattedLine.append( " " );
          spacePadNum += 1;
        }
      } else if( spaces > 1 ) {
        currentLine.erase( charNum + 1, spaces - 1 );
        spacePadNum -= spaces - 1;
      }
    } else if( shouldUnPadReturnType ) {
      if( formattedLine[formattedLine.length() - 1] == ' ' ) {
        spacePadNum -= formattedLine.length() - 1 - nextText;
        int lastText = formattedLine.find_last_not_of( " \t" );
        formattedLine.resize( lastText + 1 );
      }
      if( spaces > 0 ) {
        currentLine.erase( charNum + 1, spaces );
        spacePadNum -= spaces;
      }
    }
  }

  void ASFormatter::padObjCParamType() {
    assert( ( currentChar == '(' || currentChar == ')' ) && isInObjCMethodDefinition );
    assert( !isImmediatelyPostObjCMethodPrefix && !isInObjCReturnType );
    assert( shouldPadParamType || shouldUnPadParamType );
    if( currentChar == '(' ) {
      size_t paramOpen = formattedLine.rfind( '(' );
      assert( paramOpen != string::npos );
      size_t prevText = formattedLine.find_last_not_of( " \t", paramOpen - 1 );
      if( prevText == string::npos ) {
        return;
      }
      int spaces = paramOpen - prevText - 1;
      if( shouldPadParamType
          || objCColonPadMode == COLON_PAD_ALL
          || objCColonPadMode == COLON_PAD_AFTER ) {
        if( spaces == 0 ) {
          formattedLine.insert( paramOpen, 1, ' ' );
          spacePadNum += 1;
        }
        if( spaces > 1 ) {
          formattedLine.erase( prevText + 1, spaces - 1 );
          spacePadNum -= spaces - 1;
        }
      } else if( shouldUnPadParamType
                 || objCColonPadMode == COLON_PAD_NONE
                 || objCColonPadMode == COLON_PAD_BEFORE ) {
        if( spaces > 0 ) {
          formattedLine.erase( prevText + 1, spaces );
          spacePadNum -= spaces;
        }
      }
    } else if( currentChar == ')' ) {
      size_t nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
      if( nextText == string::npos ) {
        return;
      }
      int spaces = nextText - charNum - 1;
      if( shouldPadParamType ) {
        if( spaces == 0 ) {
          if( formattedLine[formattedLine.length() - 1] != ' ' ) {
            formattedLine.append( " " );
            spacePadNum += 1;
          }
        } else if( spaces > 1 ) {
          currentLine.erase( charNum + 1, spaces - 1 );
          spacePadNum -= spaces - 1;
        }
      } else if( shouldUnPadParamType ) {
        if( formattedLine[formattedLine.length() - 1] == ' ' ) {
          spacePadNum -= 1;
          int lastText = formattedLine.find_last_not_of( " \t" );
          formattedLine.resize( lastText + 1 );
        }
        if( spaces > 0 ) {
          currentLine.erase( charNum + 1, spaces );
          spacePadNum -= spaces;
        }
      }
    }
  }

  void ASFormatter::formatOpeningBrace( BraceType braceType ) {
    assert( !isBraceType( braceType, ARRAY_TYPE ) );
    assert( currentChar == '{' );
    parenStack->emplace_back( 0 );
    bool breakBrace = isCurrentBraceBroken();
    if( breakBrace ) {
      if( isBeforeAnyComment() && isOkToBreakBlock( braceType ) ) {
        if( isBeforeAnyLineEndComment( charNum ) && !currentLineBeginsWithBrace ) {
          currentChar = ' ';
          if( parenStack->size() > 1 ) {
            parenStack->pop_back();
          }
          currentLine[charNum] = currentChar;
          appendOpeningBrace = true;
        } else if( !isBeforeMultipleLineEndComments( charNum ) ) {
          breakLine();
        }
      } else if( !isBraceType( braceType, SINGLE_LINE_TYPE ) ) {
        formattedLine = rtrim( formattedLine );
        breakLine();
      } else if( ( shouldBreakOneLineBlocks || isBraceType( braceType, BREAK_BLOCK_TYPE ) )
                 && !isBraceType( braceType, EMPTY_BLOCK_TYPE ) ) {
        breakLine();
      } else if( !isInLineBreak ) {
        appendSpacePad();
      }
      appendCurrentChar();
      if( isBeforeComment()
          && formattedLine.length() > 0
          && formattedLine[0] == '{'
          && isOkToBreakBlock( braceType )
          && ( braceFormatMode == BREAK_MODE
               || braceFormatMode == LINUX_MODE ) ) {
        shouldBreakLineAtNextChar = true;
      }
    } else {
      if( isCharImmediatelyPostComment || isCharImmediatelyPostLineComment ) {
        if( isOkToBreakBlock( braceType )
            && !( isCharImmediatelyPostComment && isCharImmediatelyPostLineComment )
            && !isImmediatelyPostPreprocessor
            && previousCommandChar != '{'
            && previousCommandChar != '}'
            && previousCommandChar != ';' ) {
          appendCharInsideComments();
        } else
        { appendCurrentChar(); }
      } else if( previousCommandChar == '{'
                 || ( previousCommandChar == '}' && !isInClassInitializer )
                 || previousCommandChar == ';' ) {
        appendCurrentChar();
      } else {
        if( isEmptyLine( formattedLine ) ) {
          appendCurrentChar();
        } else if( isOkToBreakBlock( braceType )
                   && !( isImmediatelyPostPreprocessor
                         && currentLineBeginsWithBrace ) ) {
          if( !isBraceType( braceType, EMPTY_BLOCK_TYPE ) ) {
            appendSpacePad();
            appendCurrentChar( false );
            testForTimeToSplitFormattedLine();
            if( isBeforeComment()
                && !isBeforeMultipleLineEndComments( charNum )
                && ( !isBeforeAnyLineEndComment( charNum ) || currentLineBeginsWithBrace ) ) {
              shouldBreakLineAtNextChar = true;
              currentLine.insert( charNum + 1, charNum + 1, ' ' );
            } else if( !isBeforeAnyComment() )
            { shouldBreakLineAtNextChar = true; }
          } else {
            if( currentLineBeginsWithBrace && charNum == ( int ) currentLineFirstBraceNum ) {
              appendSpacePad();
              appendCurrentChar( false );
              shouldBreakLineAtNextChar = true;
            } else {
              appendSpacePad();
              appendCurrentChar();
            }
          }
        } else {
          if( !isInLineBreak ) {
            appendSpacePad();
          }
          appendCurrentChar();
        }
      }
    }
  }

  void ASFormatter::formatClosingBrace( BraceType braceType ) {
    assert( !isBraceType( braceType, ARRAY_TYPE ) );
    assert( currentChar == '}' );
    if( parenStack->size() > 1 ) {
      parenStack->pop_back();
    }
    if( previousCommandChar == '{' ) {
      isImmediatelyPostEmptyBlock = true;
    }
    if( attachClosingBraceMode ) {
      if( ( isEmptyLine( formattedLine )
            || isCharImmediatelyPostLineComment
            || isCharImmediatelyPostComment
            || ( isImmediatelyPostPreprocessor && ( int ) currentLine.find_first_not_of( " \t" ) == charNum )
          )
          && ( !isBraceType( braceType, SINGLE_LINE_TYPE ) || isOkToBreakBlock( braceType ) ) ) {
        breakLine();
        appendCurrentChar();
      } else {
        if( previousNonWSChar != '{' && ( !isBraceType( braceType, SINGLE_LINE_TYPE ) || isOkToBreakBlock( braceType ) ) ) {
          appendSpacePad();
        }
        appendCurrentChar( false );
      }
    } else if( !isBraceType( braceType, EMPTY_BLOCK_TYPE )
               && ( isBraceType( braceType, BREAK_BLOCK_TYPE )
                    || isOkToBreakBlock( braceType ) ) ) {
      breakLine();
      appendCurrentChar();
    } else
    { appendCurrentChar(); }
    if( isLegalNameChar( peekNextChar() ) ) {
      appendSpaceAfter();
    }
    if( shouldBreakBlocks
        && currentHeader != nullptr
        && !isHeaderInMultiStatementLine
        && parenStack->back() == 0 ) {
      if( currentHeader == &AS_CASE || currentHeader == &AS_DEFAULT ) {
        string nextText = peekNextText( currentLine.substr( charNum + 1 ) );
        if( nextText.length() > 0 && nextText.substr( 0, 5 ) != "break" ) {
          isAppendPostBlockEmptyLineRequested = true;
        }
      } else
      { isAppendPostBlockEmptyLineRequested = true; }
    }
  }

  void ASFormatter::formatArrayBraces( BraceType braceType, bool isOpeningArrayBrace ) {
    assert( isBraceType( braceType, ARRAY_TYPE ) );
    assert( currentChar == '{' || currentChar == '}' );
    if( currentChar == '{' ) {
      if( isOpeningArrayBrace ) {
        if( braceFormatMode == ATTACH_MODE
            || braceFormatMode == LINUX_MODE ) {
          if( isBraceType( braceType, ENUM_TYPE )
              && formattingStyle == STYLE_MOZILLA ) {
            isInLineBreak = true;
            appendCurrentChar();
          } else if( ( isImmediatelyPostPreprocessor
                       || ( formattedLine.length() > 0
                            && formattedLine[formattedLine.length() - 1] == '\\' ) )
                     && currentLineBeginsWithBrace ) {
            isInLineBreak = true;
            appendCurrentChar();
          } else if( isCharImmediatelyPostComment ) {
            appendCurrentChar();
          } else if( isCharImmediatelyPostLineComment && !isBraceType( braceType, SINGLE_LINE_TYPE ) ) {
            appendCharInsideComments();
          } else {
            if( isEmptyLine( formattedLine ) )
            { appendCurrentChar(); }
            else {
              if( currentLineBeginsWithBrace
                  && !isBraceType( braceType, SINGLE_LINE_TYPE ) ) {
                appendSpacePad();
                appendCurrentChar( false );
                testForTimeToSplitFormattedLine();
                if( currentLineBeginsWithBrace
                    && ( int ) currentLineFirstBraceNum == charNum )
                { shouldBreakLineAtNextChar = true; }
              } else {
                if( previousNonWSChar != '(' ) {
                  if( !isBraceType( braceType, INIT_TYPE ) )
                  { appendSpacePad(); }
                }
                appendCurrentChar();
              }
            }
          }
        } else if( braceFormatMode == BREAK_MODE ) {
          if( isWhiteSpace( peekNextChar() ) && !isInVirginLine ) {
            breakLine();
          } else if( isBeforeAnyComment() ) {
            if( isBeforeAnyLineEndComment( charNum ) && !currentLineBeginsWithBrace ) {
              currentChar = ' ';
              appendOpeningBrace = true;
            }
          }
          if( !isInLineBreak && previousNonWSChar != '(' ) {
            if( !isBraceType( braceType, INIT_TYPE ) ) {
              appendSpacePad();
            }
          }
          appendCurrentChar();
          if( currentLineBeginsWithBrace
              && ( int ) currentLineFirstBraceNum == charNum
              && !isBraceType( braceType, SINGLE_LINE_TYPE ) ) {
            shouldBreakLineAtNextChar = true;
          }
        } else if( braceFormatMode == RUN_IN_MODE ) {
          if( isWhiteSpace( peekNextChar() ) && !isInVirginLine ) {
            breakLine();
          } else if( isBeforeAnyComment() ) {
            if( isBeforeAnyLineEndComment( charNum ) && !currentLineBeginsWithBrace ) {
              currentChar = ' ';
              appendOpeningBrace = true;
            }
          }
          if( !isInLineBreak && previousNonWSChar != '(' ) {
            if( !isBraceType( braceType, INIT_TYPE ) ) {
              appendSpacePad();
            }
          }
          appendCurrentChar();
        } else if( braceFormatMode == NONE_MODE ) {
          if( currentLineBeginsWithBrace
              && charNum == ( int ) currentLineFirstBraceNum ) {
            appendCurrentChar();
          } else {
            if( previousNonWSChar != '(' ) {
              if( !isBraceType( braceType, INIT_TYPE ) )
              { appendSpacePad(); }
            }
            appendCurrentChar( false );
          }
        }
      } else {
        if( braceFormatMode == RUN_IN_MODE ) {
          if( previousNonWSChar == '{'
              && braceTypeStack->size() > 2
              && !isBraceType( ( *braceTypeStack )[braceTypeStack->size() - 2],
                               SINGLE_LINE_TYPE ) ) {
            formatArrayRunIn();
          }
        } else if( !isInLineBreak
                   && !isWhiteSpace( peekNextChar() )
                   && previousNonWSChar == '{'
                   && braceTypeStack->size() > 2
                   && !isBraceType( ( *braceTypeStack )[braceTypeStack->size() - 2], SINGLE_LINE_TYPE ) ) {
          formatArrayRunIn();
        }
        appendCurrentChar();
      }
    } else if( currentChar == '}' ) {
      if( attachClosingBraceMode ) {
        if( isEmptyLine( formattedLine )
            || isImmediatelyPostPreprocessor
            || isCharImmediatelyPostLineComment
            || isCharImmediatelyPostComment ) {
          appendCurrentChar();
        } else {
          appendSpacePad();
          appendCurrentChar( false );
        }
      } else {
        if( !isBraceType( braceType, INIT_TYPE )
            && ( !isBraceType( braceType, SINGLE_LINE_TYPE )
                 || formattedLine.find( '{' ) == string::npos ) ) {
          breakLine();
        }
        appendCurrentChar();
      }
      char peekedChar = peekNextChar();
      if( isLegalNameChar( peekedChar )
          || peekedChar == '[' ) {
        appendSpaceAfter();
      }
    }
  }

  void ASFormatter::formatRunIn() {
    assert( braceFormatMode == RUN_IN_MODE || braceFormatMode == NONE_MODE );
    if( formattingStyle != STYLE_PICO && !isOkToBreakBlock( braceTypeStack->back() ) ) {
      return;
    }
    size_t lastText = formattedLine.find_last_not_of( " \t" );
    if( lastText == string::npos || formattedLine[lastText] != '{' ) {
      return;
    }
    if( formattedLine.find_first_not_of( " \t{" ) != string::npos ) {
      return;
    }
    if( isBraceType( braceTypeStack->back(), NAMESPACE_TYPE ) ) {
      return;
    }
    bool extraIndent = false;
    bool extraHalfIndent = false;
    isInLineBreak = true;
    if( isCStyle()
        && isCharPotentialHeader( currentLine, charNum )
        && ( isBraceType( braceTypeStack->back(), CLASS_TYPE )
             || ( isBraceType( braceTypeStack->back(), STRUCT_TYPE )
                  && isInIndentableStruct ) ) ) {
      if( findKeyword( currentLine, charNum, AS_PUBLIC )
          || findKeyword( currentLine, charNum, AS_PRIVATE )
          || findKeyword( currentLine, charNum, AS_PROTECTED ) ) {
        if( getModifierIndent() ) {
          extraHalfIndent = true;
        } else if( !getClassIndent() ) {
          return;
        }
      } else if( getClassIndent() ) {
        extraIndent = true;
      }
    }
    if( !getSwitchIndent()
        && isCharPotentialHeader( currentLine, charNum )
        && ( findKeyword( currentLine, charNum, AS_CASE )
             || findKeyword( currentLine, charNum, AS_DEFAULT ) ) ) {
      return;
    }
    if( getSwitchIndent()
        && !preBraceHeaderStack->empty()
        && preBraceHeaderStack->back() == &AS_SWITCH
        && ( ( isLegalNameChar( currentChar )
               && !findKeyword( currentLine, charNum, AS_CASE ) ) ) ) {
      extraIndent = true;
    }
    isInLineBreak = false;
    if( formattedLine.length() > lastText + 1
        && formattedLine.find_first_not_of( " \t", lastText + 1 ) == string::npos ) {
      formattedLine.erase( lastText + 1 );
    }
    if( extraHalfIndent ) {
      int indentLength_ = getIndentLength();
      runInIndentChars = indentLength_ / 2;
      formattedLine.append( runInIndentChars - 1, ' ' );
    } else if( getForceTabIndentation() && getIndentLength() != getTabLength() ) {
      string indent;
      int indentLength_ = getIndentLength();
      int tabLength_ = getTabLength();
      indent.append( indentLength_, ' ' );
      if( extraIndent ) {
        indent.append( indentLength_, ' ' );
      }
      size_t tabCount = indent.length() / tabLength_;
      indent.replace( 0U, tabCount * tabLength_, tabCount, '\t' );
      runInIndentChars = indentLength_;
      if( indent[0] == ' ' ) {
        indent.erase( 0, 1 );
      }
      formattedLine.append( indent );
    } else if( getIndentString() == "\t" ) {
      appendChar( '\t', false );
      runInIndentChars = 2;
      if( extraIndent ) {
        appendChar( '\t', false );
        runInIndentChars++;
      }
    } else {
      int indentLength_ = getIndentLength();
      formattedLine.append( indentLength_ - 1, ' ' );
      runInIndentChars = indentLength_;
      if( extraIndent ) {
        formattedLine.append( indentLength_, ' ' );
        runInIndentChars += indentLength_;
      }
    }
    isInBraceRunIn = true;
  }

  void ASFormatter::formatArrayRunIn() {
    assert( isBraceType( braceTypeStack->back(), ARRAY_TYPE ) );
    if( formattedLine.find_first_not_of( " \t{" ) != string::npos ) {
      return;
    }
    size_t lastText = formattedLine.find_last_not_of( " \t" );
    if( lastText == string::npos || formattedLine[lastText] != '{' ) {
      return;
    }
    if( formattedLine.length() > lastText + 1 && formattedLine.find_first_not_of( " \t", lastText + 1 ) == string::npos ) {
      formattedLine.erase( lastText + 1 );
    }
    if( getIndentString() == "\t" ) {
      appendChar( '\t', false );
      runInIndentChars = 2;
    } else {
      int indent = getIndentLength();
      formattedLine.append( indent - 1, ' ' );
      runInIndentChars = indent;
    }
    isInBraceRunIn = true;
    isInLineBreak = false;
  }

  void ASFormatter::deleteContainer( vector<BraceType>*& container ) {
    if( container != nullptr ) {
      container->clear();
      delete( container );
      container = nullptr;
    }
  }

  template<typename T>
  void ASFormatter::deleteContainer( T & container ) {
    if( container != nullptr ) {
      container->clear();
      delete( container );
      container = nullptr;
    }
  }

  void ASFormatter::initContainer( vector<BraceType>*& container, vector<BraceType>* value ) {
    if( container != nullptr ) {
      deleteContainer( container );
    }
    container = value;
  }

  template<typename T>
  void ASFormatter::initContainer( T & container, T value ) {
    if( container != nullptr ) {
      deleteContainer( container );
    }
    container = value;
  }

  void ASFormatter::convertTabToSpaces() {
    assert( currentChar == '\t' );
    if( isInQuote || isInQuoteContinuation ) {
      return;
    }
    size_t tabSize = getTabLength();
    size_t numSpaces = tabSize - ( ( tabIncrementIn + charNum ) % tabSize );
    currentLine.replace( charNum, 1, numSpaces, ' ' );
    currentChar = currentLine[charNum];
  }

  bool ASFormatter::isOkToBreakBlock( BraceType braceType ) const {
    if( isBraceType( braceType, ARRAY_TYPE )
        && isBraceType( braceType, SINGLE_LINE_TYPE ) ) {
      return false;
    }
    if( isBraceType( braceType, COMMAND_TYPE )
        && isBraceType( braceType, EMPTY_BLOCK_TYPE ) ) {
      return false;
    }
    if( !isBraceType( braceType, SINGLE_LINE_TYPE )
        || isBraceType( braceType, BREAK_BLOCK_TYPE )
        || shouldBreakOneLineBlocks ) {
      return true;
    }
    return false;
  }

  bool ASFormatter::isSharpStyleWithParen( const string * header ) const {
    return ( isSharpStyle() && peekNextChar() == '('
             && ( header == &AS_CATCH
                  || header == &AS_DELEGATE ) );
  }

  const string* ASFormatter::checkForHeaderFollowingComment( const string & firstLine ) const {
    assert( isInComment || isInLineComment );
    assert( shouldBreakElseIfs || shouldBreakBlocks || isInSwitchStatement() );
    bool endOnEmptyLine = ( currentHeader == nullptr );
    if( isInSwitchStatement() ) {
      endOnEmptyLine = false;
    }
    string nextText = peekNextText( firstLine, endOnEmptyLine );
    if( nextText.length() == 0 || !isCharPotentialHeader( nextText, 0 ) ) {
      return nullptr;
    }
    return ASBase::findHeader( nextText, 0, headers );
  }

  void ASFormatter::processPreprocessor() {
    assert( currentChar == '#' );
    const size_t preproc = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( preproc == string::npos ) {
      return;
    }
    if( currentLine.compare( preproc, 2, "if" ) == 0 ) {
      preprocBraceTypeStackSize = braceTypeStack->size();
    } else if( currentLine.compare( preproc, 4, "else" ) == 0 ) {
      if( preprocBraceTypeStackSize > 0 ) {
        int addedPreproc = braceTypeStack->size() - preprocBraceTypeStackSize;
        for( int i = 0; i < addedPreproc; i++ ) {
          braceTypeStack->pop_back();
        }
      }
    }
  }

  bool ASFormatter::commentAndHeaderFollows() {
    assert( shouldDeleteEmptyLines && shouldBreakBlocks );
    auto stream = make_shared<ASPeekStream>( sourceIterator );
    if( !stream->hasMoreLines() ) {
      return false;
    }
    string nextLine_ = stream->peekNextLine();
    size_t firstChar = nextLine_.find_first_not_of( " \t" );
    if( firstChar == string::npos
        || !( nextLine_.compare( firstChar, 2, "//" ) == 0
              || nextLine_.compare( firstChar, 2, "/*" ) == 0 ) ) {
      return false;
    }
    string nextText = peekNextText( nextLine_, false, stream );
    if( nextText.length() == 0 || !isCharPotentialHeader( nextText, 0 ) ) {
      return false;
    }
    const string* newHeader = ASBase::findHeader( nextText, 0, headers );
    if( newHeader == nullptr ) {
      return false;
    }
    if( isClosingHeader( newHeader ) && !shouldBreakClosingHeaderBlocks ) {
      isAppendPostBlockEmptyLineRequested = false;
      return false;
    }
    return true;
  }

  bool ASFormatter::isCurrentBraceBroken() const {
    assert( braceTypeStack->size() > 1 );
    bool breakBrace = false;
    size_t stackEnd = braceTypeStack->size() - 1;
    if( shouldAttachExternC
        && isBraceType( ( *braceTypeStack )[stackEnd], EXTERN_TYPE ) ) {
      return false;
    }
    if( shouldAttachNamespace
        && isBraceType( ( *braceTypeStack )[stackEnd], NAMESPACE_TYPE ) ) {
      return false;
    }
    if( shouldAttachClass
        && ( isBraceType( ( *braceTypeStack )[stackEnd], CLASS_TYPE )
             || isBraceType( ( *braceTypeStack )[stackEnd], INTERFACE_TYPE ) ) ) {
      return false;
    }
    if( shouldAttachInline
        && isCStyle()
        && braceFormatMode != RUN_IN_MODE
        && !( currentLineBeginsWithBrace && peekNextChar() == '/' )
        && isBraceType( ( *braceTypeStack )[stackEnd], COMMAND_TYPE ) ) {
      size_t i;
      for( i = 1; i < braceTypeStack->size(); i++ )
        if( isBraceType( ( *braceTypeStack )[i], CLASS_TYPE )
            || isBraceType( ( *braceTypeStack )[i], STRUCT_TYPE ) ) {
          return false;
        }
    }
    if( isBraceType( ( *braceTypeStack )[stackEnd], EXTERN_TYPE ) ) {
      if( currentLineBeginsWithBrace
          || braceFormatMode == RUN_IN_MODE ) {
        breakBrace = true;
      }
    } else if( braceFormatMode == NONE_MODE ) {
      if( currentLineBeginsWithBrace
          && ( int ) currentLineFirstBraceNum == charNum ) {
        breakBrace = true;
      }
    } else if( braceFormatMode == BREAK_MODE || braceFormatMode == RUN_IN_MODE ) {
      breakBrace = true;
    } else if( braceFormatMode == LINUX_MODE ) {
      if( isBraceType( ( *braceTypeStack )[stackEnd], NAMESPACE_TYPE ) ) {
        if( formattingStyle != STYLE_STROUSTRUP
            && formattingStyle != STYLE_MOZILLA ) {
          breakBrace = true;
        }
      } else if( isBraceType( ( *braceTypeStack )[stackEnd], CLASS_TYPE )
                 || isBraceType( ( *braceTypeStack )[stackEnd], INTERFACE_TYPE ) ) {
        if( formattingStyle != STYLE_STROUSTRUP ) {
          breakBrace = true;
        }
      } else if( isBraceType( ( *braceTypeStack )[stackEnd], STRUCT_TYPE ) ) {
        if( formattingStyle == STYLE_MOZILLA ) {
          breakBrace = true;
        }
      } else if( isBraceType( ( *braceTypeStack )[stackEnd], COMMAND_TYPE ) ) {
        if( stackEnd == 1 ) {
          breakBrace = true;
        } else if( stackEnd > 1 ) {
          if( isBraceType( ( *braceTypeStack )[stackEnd - 1], NAMESPACE_TYPE )
              || isBraceType( ( *braceTypeStack )[stackEnd - 1], CLASS_TYPE )
              || isBraceType( ( *braceTypeStack )[stackEnd - 1], ARRAY_TYPE )
              || isBraceType( ( *braceTypeStack )[stackEnd - 1], STRUCT_TYPE )
              || isBraceType( ( *braceTypeStack )[stackEnd - 1], EXTERN_TYPE ) ) {
            breakBrace = true;
          }
        }
      }
    }
    return breakBrace;
  }

  void ASFormatter::formatCommentBody() {
    assert( isInComment );
    while( charNum < ( int ) currentLine.length() ) {
      currentChar = currentLine[charNum];
      if( isSequenceReached( "*/" ) ) {
        formatCommentCloser();
        break;
      }
      if( currentChar == '\t' && shouldConvertTabs ) {
        convertTabToSpaces();
      }
      appendCurrentChar();
      ++charNum;
    }
    if( shouldStripCommentPrefix ) {
      stripCommentPrefix();
    }
  }

  void ASFormatter::formatCommentOpener() {
    assert( isSequenceReached( "/*" ) );
    isInComment = isInCommentStartLine = true;
    isImmediatelyPostLineComment = false;
    if( previousNonWSChar == '}' ) {
      resetEndOfStatement();
    }
    const string* followingHeader = nullptr;
    if( ( doesLineStartComment
          && !isImmediatelyPostCommentOnly
          && isBraceType( braceTypeStack->back(), COMMAND_TYPE ) )
        && ( shouldBreakElseIfs
             || isInSwitchStatement()
             || ( shouldBreakBlocks
                  && !isImmediatelyPostEmptyLine
                  && previousCommandChar != '{' ) ) ) {
      followingHeader = checkForHeaderFollowingComment( currentLine.substr( charNum ) );
    }
    if( spacePadNum != 0 && !isInLineBreak ) {
      adjustComments();
    }
    formattedLineCommentNum = formattedLine.length();
    if( previousCommandChar == '{'
        && !isImmediatelyPostComment
        && !isImmediatelyPostLineComment ) {
      if( isBraceType( braceTypeStack->back(), NAMESPACE_TYPE ) ) {
        isInLineBreak = true;
      } else if( braceFormatMode == NONE_MODE ) {
        if( currentLineBeginsWithBrace ) {
          formatRunIn();
        }
      } else if( braceFormatMode == ATTACH_MODE ) {
        if( formattedLine.length() > 0 && formattedLine[0] == '{'
            && !isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE ) ) {
          isInLineBreak = true;
        }
      } else if( braceFormatMode == RUN_IN_MODE ) {
        if( formattedLine.length() > 0 && formattedLine[0] == '{' ) {
          formatRunIn();
        }
      }
    } else if( !doesLineStartComment ) {
      noTrimCommentContinuation = true;
    }
    if( shouldBreakElseIfs && followingHeader == &AS_ELSE ) {
      elseHeaderFollowsComments = true;
    }
    if( followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT ) {
      caseHeaderFollowsComments = true;
    }
    appendSequence( AS_OPEN_COMMENT );
    goForward( 1 );
    if( shouldBreakBlocks
        && followingHeader != nullptr
        && !isImmediatelyPostEmptyLine
        && previousCommandChar != '{' ) {
      if( isClosingHeader( followingHeader ) ) {
        if( !shouldBreakClosingHeaderBlocks ) {
          isPrependPostBlockEmptyLineRequested = false;
        }
      } else
      { isPrependPostBlockEmptyLineRequested = true; }
    }
    if( previousCommandChar == '}' ) {
      currentHeader = nullptr;
    }
  }

  void ASFormatter::formatCommentCloser() {
    assert( isSequenceReached( "*/" ) );
    isInComment = false;
    noTrimCommentContinuation = false;
    isImmediatelyPostComment = true;
    appendSequence( AS_CLOSE_COMMENT );
    goForward( 1 );
    if( doesLineStartComment
        && ( currentLine.find_first_not_of( " \t", charNum + 1 ) == string::npos ) ) {
      lineEndsInCommentOnly = true;
    }
    if( peekNextChar() == '}'
        && previousCommandChar != ';'
        && !isBraceType( braceTypeStack->back(), ARRAY_TYPE )
        && !isInPreprocessor
        && isOkToBreakBlock( braceTypeStack->back() ) ) {
      isInLineBreak = true;
      shouldBreakLineAtNextChar = true;
    }
  }

  void ASFormatter::formatLineCommentBody() {
    assert( isInLineComment );
    while( charNum < ( int ) currentLine.length() ) {
      currentChar = currentLine[charNum];
      if( currentChar == '\t' && shouldConvertTabs ) {
        convertTabToSpaces();
      }
      appendCurrentChar();
      ++charNum;
    }
    if( charNum == ( int ) currentLine.length() ) {
      isInLineBreak = true;
      isInLineComment = false;
      isImmediatelyPostLineComment = true;
      currentChar = 0;
    }
  }

  void ASFormatter::formatLineCommentOpener() {
    assert( isSequenceReached( "//" ) );
    if( ( int ) currentLine.length() > charNum + 2
        && currentLine[charNum + 2] == '\xf2' ) {
      isAppendPostBlockEmptyLineRequested = false;
    }
    isInLineComment = true;
    isCharImmediatelyPostComment = false;
    if( previousNonWSChar == '}' ) {
      resetEndOfStatement();
    }
    const string* followingHeader = nullptr;
    if( ( lineIsLineCommentOnly
          && !isImmediatelyPostCommentOnly
          && isBraceType( braceTypeStack->back(), COMMAND_TYPE ) )
        && ( shouldBreakElseIfs
             || isInSwitchStatement()
             || ( shouldBreakBlocks
                  && !isImmediatelyPostEmptyLine
                  && previousCommandChar != '{' ) ) ) {
      followingHeader = checkForHeaderFollowingComment( currentLine.substr( charNum ) );
    }
    if( ( !shouldIndentCol1Comments && !lineCommentNoIndent )
        || foundNamespaceHeader ) {
      if( charNum == 0 ) {
        lineCommentNoIndent = true;
      } else if( charNum == 1 && currentLine[0] == ' ' ) {
        lineCommentNoIndent = true;
      }
    }
    if( !lineCommentNoIndent && spacePadNum != 0 && !isInLineBreak ) {
      adjustComments();
    }
    formattedLineCommentNum = formattedLine.length();
    if( previousCommandChar == '{'
        && !isImmediatelyPostComment
        && !isImmediatelyPostLineComment ) {
      if( braceFormatMode == NONE_MODE ) {
        if( currentLineBeginsWithBrace ) {
          formatRunIn();
        }
      } else if( braceFormatMode == RUN_IN_MODE ) {
        if( !lineCommentNoIndent ) {
          formatRunIn();
        } else
        { isInLineBreak = true; }
      } else if( braceFormatMode == BREAK_MODE ) {
        if( formattedLine.length() > 0 && formattedLine[0] == '{' ) {
          isInLineBreak = true;
        }
      } else {
        if( currentLineBeginsWithBrace ) {
          isInLineBreak = true;
        }
      }
    }
    if( shouldBreakElseIfs && followingHeader == &AS_ELSE ) {
      elseHeaderFollowsComments = true;
    }
    if( followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT ) {
      caseHeaderFollowsComments = true;
    }
    appendSequence( AS_OPEN_LINE_COMMENT );
    goForward( 1 );
    if( shouldBreakBlocks
        && followingHeader != nullptr
        && !isImmediatelyPostEmptyLine
        && previousCommandChar != '{' ) {
      if( isClosingHeader( followingHeader ) ) {
        if( !shouldBreakClosingHeaderBlocks ) {
          isPrependPostBlockEmptyLineRequested = false;
        }
      } else
      { isPrependPostBlockEmptyLineRequested = true; }
    }
    if( previousCommandChar == '}' ) {
      currentHeader = nullptr;
    }
    if( getIndentString() == "\t" && lineCommentNoIndent ) {
      while( charNum + 1 < ( int ) currentLine.length()
             && currentLine[charNum + 1] == '\t' ) {
        currentChar = currentLine[++charNum];
        appendCurrentChar();
      }
    }
    if( charNum + 1 == ( int ) currentLine.length() ) {
      isInLineBreak = true;
      isInLineComment = false;
      isImmediatelyPostLineComment = true;
      currentChar = 0;
    }
  }

  void ASFormatter::formatQuoteBody() {
    assert( isInQuote );
    if( isSpecialChar ) {
      isSpecialChar = false;
    } else if( currentChar == '\\' && !isInVerbatimQuote ) {
      if( peekNextChar() == ' ' ) {
        haveLineContinuationChar = true;
      } else
      { isSpecialChar = true; }
    } else if( isInVerbatimQuote && currentChar == '"' ) {
      if( isCStyle() ) {
        string delim = ')' + verbatimDelimiter;
        int delimStart = charNum - delim.length();
        if( delimStart > 0 && currentLine.substr( delimStart, delim.length() ) == delim ) {
          isInQuote = false;
          isInVerbatimQuote = false;
        }
      } else if( isSharpStyle() ) {
        if( ( int ) currentLine.length() > charNum + 1
            && currentLine[charNum + 1] == '"' ) {
          appendSequence( "\"\"" );
          goForward( 1 );
          return;
        }
        isInQuote = false;
        isInVerbatimQuote = false;
      }
    } else if( quoteChar == currentChar ) {
      isInQuote = false;
    }
    appendCurrentChar();
    if( isInQuote && currentChar != '\\' ) {
      while( charNum + 1 < ( int ) currentLine.length()
             && currentLine[charNum + 1] != quoteChar
             && currentLine[charNum + 1] != '\\' ) {
        currentChar = currentLine[++charNum];
        appendCurrentChar();
      }
    }
    if( charNum + 1 >= ( int ) currentLine.length()
        && currentChar != '\\'
        && !isInVerbatimQuote ) {
      isInQuote = false;
    }
  }

  void ASFormatter::formatQuoteOpener() {
    assert( currentChar == '"'
            || ( currentChar == '\'' && !isDigitSeparator( currentLine, charNum ) ) );
    isInQuote = true;
    quoteChar = currentChar;
    if( isCStyle() && previousChar == 'R' ) {
      int parenPos = currentLine.find( '(', charNum );
      if( parenPos != -1 ) {
        isInVerbatimQuote = true;
        verbatimDelimiter = currentLine.substr( charNum + 1, parenPos - charNum - 1 );
      }
    } else if( isSharpStyle() && previousChar == '@' ) {
      isInVerbatimQuote = true;
    }
    if( previousCommandChar == '{'
        && !isImmediatelyPostComment
        && !isImmediatelyPostLineComment
        && isNonInStatementArray
        && !isBraceType( braceTypeStack->back(), SINGLE_LINE_TYPE )
        && !isWhiteSpace( peekNextChar() ) ) {
      if( braceFormatMode == NONE_MODE ) {
        if( currentLineBeginsWithBrace ) {
          formatRunIn();
        }
      } else if( braceFormatMode == RUN_IN_MODE ) {
        formatRunIn();
      } else if( braceFormatMode == BREAK_MODE ) {
        if( formattedLine.length() > 0 && formattedLine[0] == '{' ) {
          isInLineBreak = true;
        }
      } else {
        if( currentLineBeginsWithBrace ) {
          isInLineBreak = true;
        }
      }
    }
    previousCommandChar = ' ';
    appendCurrentChar();
  }

  int ASFormatter::getNextLineCommentAdjustment() {
    assert( foundClosingHeader && previousNonWSChar == '}' );
    if( charNum < 1 ) {
      return 0;
    }
    size_t lastBrace = currentLine.rfind( '}', charNum - 1 );
    if( lastBrace != string::npos ) {
      return ( lastBrace - charNum );
    }
    return 0;
  }

  int ASFormatter::getCurrentLineCommentAdjustment() {
    assert( foundClosingHeader && previousNonWSChar == '}' );
    if( charNum < 1 ) {
      return 2;
    }
    size_t lastBrace = currentLine.rfind( '}', charNum - 1 );
    if( lastBrace == string::npos ) {
      return 2;
    }
    return 0;
  }

  string ASFormatter::getPreviousWord( const string & line, int currPos ) const {
    if( currPos == 0 ) {
      return string();
    }
    size_t end = line.find_last_not_of( " \t", currPos - 1 );
    if( end == string::npos || !isLegalNameChar( line[end] ) ) {
      return string();
    }
    int start;
    for( start = end; start > -1; start-- ) {
      if( !isLegalNameChar( line[start] ) || line[start] == '.' ) {
        break;
      }
    }
    start++;
    return ( line.substr( start, end - start + 1 ) );
  }

  void ASFormatter::isLineBreakBeforeClosingHeader() {
    assert( foundClosingHeader && previousNonWSChar == '}' );
    if( currentHeader == &AS_WHILE && shouldAttachClosingWhile ) {
      appendClosingHeader();
      return;
    }
    if( braceFormatMode == BREAK_MODE
        || braceFormatMode == RUN_IN_MODE
        || attachClosingBraceMode ) {
      isInLineBreak = true;
    } else if( braceFormatMode == NONE_MODE ) {
      if( shouldBreakClosingHeaderBraces
          || getBraceIndent() || getBlockIndent() ) {
        isInLineBreak = true;
      } else {
        appendSpacePad();
        size_t i = currentLine.find_first_not_of( " \t" );
        if( i != string::npos && currentLine[i] == '}' ) {
          isInLineBreak = false;
        }
        if( shouldBreakBlocks ) {
          isAppendPostBlockEmptyLineRequested = false;
        }
      }
    } else {
      if( shouldBreakClosingHeaderBraces
          || getBraceIndent() || getBlockIndent() ) {
        isInLineBreak = true;
      } else {
        appendClosingHeader();
        if( shouldBreakBlocks ) {
          isAppendPostBlockEmptyLineRequested = false;
        }
      }
    }
  }

  void ASFormatter::appendClosingHeader() {
    bool previousLineIsEmpty = isEmptyLine( formattedLine );
    int previousLineIsOneLineBlock = 0;
    size_t firstBrace = findNextChar( formattedLine, '{' );
    if( firstBrace != string::npos ) {
      previousLineIsOneLineBlock = isOneLineBlockReached( formattedLine, firstBrace );
    }
    if( !previousLineIsEmpty
        && previousLineIsOneLineBlock == 0 ) {
      isInLineBreak = false;
      appendSpacePad();
      spacePadNum = 0;
    }
  }

  bool ASFormatter::addBracesToStatement() {
    assert( isImmediatelyPostHeader );
    if( currentHeader != &AS_IF
        && currentHeader != &AS_ELSE
        && currentHeader != &AS_FOR
        && currentHeader != &AS_WHILE
        && currentHeader != &AS_DO
        && currentHeader != &AS_FOREACH
        && currentHeader != &AS_QFOREACH
        && currentHeader != &AS_QFOREVER
        && currentHeader != &AS_FOREVER ) {
      return false;
    }
    if( currentHeader == &AS_WHILE && foundClosingHeader ) {
      return false;
    }
    if( currentChar == ';' ) {
      return false;
    }
    if( isCharPotentialHeader( currentLine, charNum ) )
      if( findHeader( headers ) != nullptr ) {
        return false;
      }
    size_t nextSemiColon = charNum;
    if( currentChar != ';' ) {
      nextSemiColon = findNextChar( currentLine, ';', charNum + 1 );
    }
    if( nextSemiColon == string::npos ) {
      return false;
    }
    if( nextSemiColon == currentLine.length() - 1 ) {  // 条件代码块限定符
      currentLine.append( " \n  }" );
    } else {
      currentLine.insert( nextSemiColon + 1, " }" );
    }
    currentLine.insert( charNum , "{ " );
    assert( computeChecksumIn( "{}" ) );
    currentChar = '{';
    if( ( int ) currentLine.find_first_not_of( " \t" ) == charNum ) {
      currentLineBeginsWithBrace = true;
    }
    if( !shouldAddOneLineBraces ) {
      size_t lastText = formattedLine.find_last_not_of( " \t" );
      if( ( formattedLine.length() - 1 ) - lastText > 1 ) {
        formattedLine.erase( lastText + 1 );
      }
    }
    return true;
  }

  bool ASFormatter::removeBracesFromStatement() {
    assert( isImmediatelyPostHeader );
    assert( currentChar == '{' );
    if( currentHeader != &AS_IF
        && currentHeader != &AS_ELSE
        && currentHeader != &AS_FOR
        && currentHeader != &AS_WHILE
        && currentHeader != &AS_FOREACH ) {
      return false;
    }
    if( currentHeader == &AS_WHILE && foundClosingHeader ) {
      return false;
    }
    bool isFirstLine = true;
    string nextLine_;
    if( !isBeforeAnyLineEndComment( charNum ) || currentLineBeginsWithBrace ) {
      nextLine_ = currentLine.substr( charNum + 1 );
    }
    size_t nextChar = 0;
    ASPeekStream stream( sourceIterator );
    while( stream.hasMoreLines() || isFirstLine ) {
      if( isFirstLine ) {
        isFirstLine = false;
      } else {
        nextLine_ = stream.peekNextLine();
        nextChar = 0;
      }
      nextChar = nextLine_.find_first_not_of( " \t", nextChar );
      if( nextChar != string::npos ) {
        break;
      }
    }
    if( ( nextLine_.compare( nextChar, 2, "/*" ) == 0 )
        || ( nextLine_.compare( nextChar, 2, "//" ) == 0 )
        || ( isCharPotentialHeader( nextLine_, nextChar )
             && ASBase::findHeader( nextLine_, nextChar, headers ) != nullptr ) ) {
      return false;
    }
    size_t nextSemiColon = nextChar;
    if( nextLine_[nextChar] != ';' ) {
      nextSemiColon = findNextChar( nextLine_, ';', nextChar + 1 );
    }
    if( nextSemiColon == string::npos ) {
      return false;
    }
    isFirstLine = true;
    nextChar = nextSemiColon + 1;
    while( stream.hasMoreLines() || isFirstLine ) {
      if( isFirstLine ) {
        isFirstLine = false;
      } else {
        nextLine_ = stream.peekNextLine();
        nextChar = 0;
      }
      nextChar = nextLine_.find_first_not_of( " \t", nextChar );
      if( nextChar != string::npos ) {
        break;
      }
    }
    if( nextLine_.length() == 0 || nextLine_[nextChar] != '}' ) {
      return false;
    }
    currentLine[charNum] = currentChar = ' ';
    assert( adjustChecksumIn( -'{' ) );
    return true;
  }

  size_t ASFormatter::findNextChar( const string& line, char searchChar, int searchStart ) const {
    size_t i;
    for( i = searchStart; i < line.length(); i++ ) {
      if( line.compare( i, 2, "//" ) == 0 ) {
        return string::npos;
      }
      if( line.compare( i, 2, "/*" ) == 0 ) {
        size_t endComment = line.find( "*/", i + 2 );
        if( endComment == string::npos ) {
          return string::npos;
        }
        i = endComment + 2;
        if( i >= line.length() ) {
          return string::npos;
        }
      }
      if( line[i] == '"'
          || ( line[i] == '\'' && !isDigitSeparator( line, i ) ) ) {
        char quote = line[i];
        while( i < line.length() ) {
          size_t endQuote = line.find( quote, i + 1 );
          if( endQuote == string::npos ) {
            return string::npos;
          }
          i = endQuote;
          if( line[endQuote - 1] != '\\' ) {
            break;
          }
          if( line[endQuote - 2] == '\\' ) {
            break;
          }
        }
      }
      if( line[i] == searchChar ) {
        break;
      }
      if( line[i] == '{' ) {
        return string::npos;
      }
    }
    if( i >= line.length() ) {
      return string::npos;
    }
    return i;
  }

  bool ASFormatter::isStructAccessModified( const string & firstLine, size_t index ) const {
    assert( firstLine[index] == '{' );
    assert( isCStyle() );
    bool isFirstLine = true;
    size_t braceCount = 1;
    string nextLine_ = firstLine.substr( index + 1 );
    ASPeekStream stream( sourceIterator );
    bool isInComment_ = false;
    bool isInQuote_ = false;
    char quoteChar_ = ' ';
    while( stream.hasMoreLines() || isFirstLine ) {
      if( isFirstLine ) {
        isFirstLine = false;
      } else
      { nextLine_ = stream.peekNextLine(); }
      for( size_t i = 0; i < nextLine_.length(); i++ ) {
        if( isWhiteSpace( nextLine_[i] ) ) {
          continue;
        }
        if( nextLine_.compare( i, 2, "/*" ) == 0 ) {
          isInComment_ = true;
        }
        if( isInComment_ ) {
          if( nextLine_.compare( i, 2, "*/" ) == 0 ) {
            isInComment_ = false;
            ++i;
          }
          continue;
        }
        if( nextLine_[i] == '\\' ) {
          ++i;
          continue;
        }
        if( isInQuote_ ) {
          if( nextLine_[i] == quoteChar_ ) {
            isInQuote_ = false;
          }
          continue;
        }
        if( nextLine_[i] == '"'
            || ( nextLine_[i] == '\'' && !isDigitSeparator( nextLine_, i ) ) ) {
          isInQuote_ = true;
          quoteChar_ = nextLine_[i];
          continue;
        }
        if( nextLine_.compare( i, 2, "//" ) == 0 ) {
          i = nextLine_.length();
          continue;
        }
        if( nextLine_[i] == '{' ) {
          ++braceCount;
        }
        if( nextLine_[i] == '}' ) {
          --braceCount;
        }
        if( braceCount == 0 ) {
          return false;
        }
        if( isCharPotentialHeader( nextLine_, i ) ) {
          if( findKeyword( nextLine_, i, AS_PUBLIC )
              || findKeyword( nextLine_, i, AS_PRIVATE )
              || findKeyword( nextLine_, i, AS_PROTECTED ) ) {
            return true;
          }
          string name = getCurrentWord( nextLine_, i );
          i += name.length() - 1;
        }
      }
    }
    return false;
  }

  bool ASFormatter::isIndentablePreprocessorBlock( const string& firstLine, size_t index ) {
    assert( firstLine[index] == '#' );
    bool isFirstLine = true;
    bool isInIndentableBlock = false;
    bool blockContainsBraces = false;
    bool blockContainsDefineContinuation = false;
    bool isInClassConstructor = false;
    bool isPotentialHeaderGuard = false;
    bool isPotentialHeaderGuard2 = false;
    int  numBlockIndents = 0;
    int  lineParenCount = 0;
    string nextLine_ = firstLine.substr( index );
    auto stream = make_shared<ASPeekStream>( sourceIterator );
    bool isInComment_ = false;
    bool isInQuote_ = false;
    char quoteChar_ = ' ';
    while( stream->hasMoreLines() || isFirstLine ) {
      if( isFirstLine ) {
        isFirstLine = false;
      } else
      { nextLine_ = stream->peekNextLine(); }
      for( size_t i = 0; i < nextLine_.length(); i++ ) {
        if( isWhiteSpace( nextLine_[i] ) ) {
          continue;
        }
        if( nextLine_.compare( i, 2, "/*" ) == 0 ) {
          isInComment_ = true;
        }
        if( isInComment_ ) {
          if( nextLine_.compare( i, 2, "*/" ) == 0 ) {
            isInComment_ = false;
            ++i;
          }
          continue;
        }
        if( nextLine_[i] == '\\' ) {
          ++i;
          continue;
        }
        if( isInQuote_ ) {
          if( nextLine_[i] == quoteChar_ ) {
            isInQuote_ = false;
          }
          continue;
        }
        if( nextLine_[i] == '"'
            || ( nextLine_[i] == '\'' && !isDigitSeparator( nextLine_, i ) ) ) {
          isInQuote_ = true;
          quoteChar_ = nextLine_[i];
          continue;
        }
        if( nextLine_.compare( i, 2, "//" ) == 0 ) {
          i = nextLine_.length();
          continue;
        }
        if( nextLine_[i] == '#' ) {
          string preproc = ASBeautifier::extractPreprocessorStatement( nextLine_ );
          if( preproc.length() >= 2 && preproc.substr( 0, 2 ) == "if" ) {
            numBlockIndents += 1;
            isInIndentableBlock = true;
            if( !processedFirstConditional ) {
              processedFirstConditional = true;
              isFirstPreprocConditional = true;
              if( isNDefPreprocStatement( nextLine_, preproc ) )
              { isPotentialHeaderGuard = true; }
            }
          } else if( preproc == "endif" ) {
            if( numBlockIndents > 0 )
            { numBlockIndents -= 1; }
            if( numBlockIndents == 0 )
            { goto EndOfWhileLoop; }
          } else if( preproc == "define" ) {
            if( nextLine_[nextLine_.length() - 1] == '\\' )
            { blockContainsDefineContinuation = true; }
            else if( isPotentialHeaderGuard && numBlockIndents == 1 )
            { isPotentialHeaderGuard2 = true; }
          }
          i = nextLine_.length();
          continue;
        }
        if( nextLine_[i] == '{' || nextLine_[i] == '}' ) {
          blockContainsBraces = true;
        } else if( nextLine_[i] == '(' ) {
          ++lineParenCount;
        } else if( nextLine_[i] == ')' ) {
          --lineParenCount;
        } else if( nextLine_[i] == ':' ) {
          if( nextLine_.length() > i && nextLine_[i + 1] == ':' ) {
            ++i;
          } else
          { isInClassConstructor = true; }
        }
        if( blockContainsBraces || isInClassConstructor || blockContainsDefineContinuation ) {
          goto EndOfWhileLoop;
        }
      }
      if( lineParenCount != 0 ) {
        break;
      }
    }
  EndOfWhileLoop:
    preprocBlockEnd = sourceIterator->tellg();
    if( preprocBlockEnd < 0 ) {
      preprocBlockEnd = sourceIterator->getStreamLength();
    }
    if( blockContainsBraces
        || isInClassConstructor
        || blockContainsDefineContinuation
        || lineParenCount != 0
        || numBlockIndents != 0 ) {
      isInIndentableBlock = false;
    }
    string nextText = peekNextText( "", false, stream );
    if( isFirstPreprocConditional ) {
      isFirstPreprocConditional = false;
      if( nextText.empty() && isPotentialHeaderGuard2 ) {
        isInIndentableBlock = false;
        preprocBlockEnd = 0;
      }
    }
    if( !isInIndentableBlock ) {
      preprocBlockEnd = 0;
    }
    return isInIndentableBlock;
  }

  bool ASFormatter::isNDefPreprocStatement( const string& nextLine_, const string& preproc ) const {
    if( preproc == "ifndef" ) {
      return true;
    }
    if( preproc == "if" ) {
      size_t i = nextLine_.find( '!' );
      if( i == string::npos ) {
        return false;
      }
      i = nextLine_.find_first_not_of( " \t", ++i );
      if( i != string::npos && nextLine_.compare( i, 7, "defined" ) == 0 ) {
        return true;
      }
    }
    return false;
  }

  bool ASFormatter::isExecSQL( const string& line, size_t index ) const {
    if( line[index] != 'e' && line[index] != 'E' ) {
      return false;
    }
    string word;
    if( isCharPotentialHeader( line, index ) ) {
      word = getCurrentWord( line, index );
    }
    for( size_t i = 0; i < word.length(); i++ ) {
      word[i] = ( char ) toupper( word[i] );
    }
    if( word != "EXEC" ) {
      return false;
    }
    size_t index2 = index + word.length();
    index2 = line.find_first_not_of( " \t", index2 );
    if( index2 == string::npos ) {
      return false;
    }
    word.erase();
    if( isCharPotentialHeader( line, index2 ) ) {
      word = getCurrentWord( line, index2 );
    }
    for( size_t i = 0; i < word.length(); i++ ) {
      word[i] = ( char ) toupper( word[i] );
    }
    if( word != "SQL" ) {
      return false;
    }
    return true;
  }

  void ASFormatter::trimContinuationLine() {
    size_t len = currentLine.length();
    size_t tabSize = getTabLength();
    charNum = 0;
    if( leadingSpaces > 0 && len > 0 ) {
      size_t i;
      size_t continuationIncrementIn = 0;
      for( i = 0; ( i < len ) && ( i + continuationIncrementIn < leadingSpaces ); i++ ) {
        if( !isWhiteSpace( currentLine[i] ) ) {
          if( i < continuationIncrementIn ) {
            leadingSpaces = i + tabIncrementIn;
          }
          continuationIncrementIn = tabIncrementIn;
          break;
        }
        if( currentLine[i] == '\t' ) {
          continuationIncrementIn += tabSize - 1 - ( ( continuationIncrementIn + i ) % tabSize );
        }
      }
      if( ( int ) continuationIncrementIn == tabIncrementIn ) {
        charNum = i;
      } else {
        string newLine;
        int leadingChars = 0;
        if( ( int ) leadingSpaces > tabIncrementIn ) {
          leadingChars = leadingSpaces - tabIncrementIn;
        }
        newLine.append( leadingChars, ' ' );
        newLine.append( currentLine, i, len - i );
        currentLine = newLine;
        charNum = leadingChars;
        if( currentLine.length() == 0 ) {
          currentLine = string( " " );
        }
      }
      if( i >= len ) {
        charNum = 0;
      }
    }
  }


  bool ASFormatter::isClosingHeader( const string* header ) const {
    return ( header == &AS_ELSE
             || header == &AS_CATCH
             || header == &AS_FINALLY );
  }


  bool ASFormatter::isImmediatelyPostCast() const {
    assert( previousNonWSChar == ')' && currentChar == '*' );
    string line;
    size_t paren = currentLine.rfind( ')', charNum );
    if( paren != string::npos ) {
      line = currentLine;
    } else {
      line = readyFormattedLine;
      paren = line.rfind( ')' );
      if( paren == string::npos ) {
        return false;
      }
    }
    if( paren == 0 ) {
      return false;
    }
    size_t lastChar = line.find_last_not_of( " \t", paren - 1 );
    if( lastChar == string::npos ) {
      return false;
    }
    if( line[lastChar] == '*' ) {
      return true;
    }
    return false;
  }


  void ASFormatter::checkIfTemplateOpener() {
    assert( !isInTemplate && currentChar == '<' );
    size_t firstChar = currentLine.find_first_not_of( "< \t", charNum );
    if( firstChar == string::npos
        || currentLine[firstChar] == '=' ) {
      isInTemplate = false;
      return;
    }
    bool isFirstLine = true;
    int parenDepth_ = 0;
    int maxTemplateDepth = 0;
    templateDepth = 0;
    string nextLine_ = currentLine.substr( charNum );
    ASPeekStream stream( sourceIterator );
    bool isInComment_ = false;
    bool isInQuote_ = false;
    char quoteChar_ = ' ';
    while( stream.hasMoreLines() || isFirstLine ) {
      if( isFirstLine ) {
        isFirstLine = false;
      } else
      { nextLine_ = stream.peekNextLine(); }
      for( size_t i = 0; i < nextLine_.length(); i++ ) {
        char currentChar_ = nextLine_[i];
        if( isWhiteSpace( currentChar_ ) ) {
          continue;
        }
        if( nextLine_.compare( i, 2, "/*" ) == 0 ) {
          isInComment_ = true;
        }
        if( isInComment_ ) {
          if( nextLine_.compare( i, 2, "*/" ) == 0 ) {
            isInComment_ = false;
            ++i;
          }
          continue;
        }
        if( currentChar_ == '\\' ) {
          ++i;
          continue;
        }
        if( isInQuote_ ) {
          if( currentChar_ == quoteChar_ ) {
            isInQuote_ = false;
          }
          continue;
        }
        if( currentChar_ == '"'
            || ( currentChar_ == '\'' && !isDigitSeparator( nextLine_, i ) ) ) {
          isInQuote_ = true;
          quoteChar_ = currentChar_;
          continue;
        }
        if( nextLine_.compare( i, 2, "//" ) == 0 ) {
          i = nextLine_.length();
          continue;
        }
        if( currentChar_ == '<' ) {
          ++templateDepth;
          ++maxTemplateDepth;
          continue;
        } else if( currentChar_ == '>' ) {
          --templateDepth;
          if( templateDepth == 0 ) {
            if( parenDepth_ == 0 ) {
              isInTemplate = true;
              templateDepth = maxTemplateDepth;
            }
            return;
          }
          continue;
        } else if( currentChar_ == '(' || currentChar_ == ')' ) {
          if( currentChar_ == '(' ) {
            ++parenDepth_;
          } else
          { --parenDepth_; }
          if( parenDepth_ >= 0 ) {
            continue;
          }
          isInTemplate = false;
          templateDepth = 0;
          return;
        } else if( nextLine_.compare( i, 2, AS_AND ) == 0
                   || nextLine_.compare( i, 2, AS_OR ) == 0 ) {
          isInTemplate = false;
          templateDepth = 0;
          return;
        } else if( currentChar_ == ','
                   || currentChar_ == '&'
                   || currentChar_ == '*'
                   || currentChar_ == '^'
                   || currentChar_ == ':'
                   || currentChar_ == '='
                   || currentChar_ == '['
                   || currentChar_ == ']'
                   || currentChar_ == '('
                   || currentChar_ == ')'
                   || ( isJavaStyle() && currentChar_ == '?' )
                 ) {
          continue;
        } else if( !isLegalNameChar( currentChar_ ) ) {
          isInTemplate = false;
          templateDepth = 0;
          return;
        }
        string name = getCurrentWord( nextLine_, i );
        i += name.length() - 1;
      }
    }
  }

  void ASFormatter::updateFormattedLineSplitPoints( char appendedChar ) {
    assert( maxCodeLength != string::npos );
    assert( formattedLine.length() > 0 );
    if( !isOkToSplitFormattedLine() ) {
      return;
    }
    char nextChar = peekNextChar();
    if( nextChar == '/' ) {
      return;
    }
    if( appendedChar == '{' || appendedChar == '}'
        || previousNonWSChar == '{' || previousNonWSChar == '}'
        || nextChar == '{' || nextChar == '}'
        || currentChar == '{' || currentChar == '}' ) {
      return;
    }
    if( appendedChar == '[' || appendedChar == ']'
        || previousNonWSChar == '['
        || nextChar == '[' || nextChar == ']' ) {
      return;
    }
    if( isWhiteSpace( appendedChar ) ) {
      if( nextChar != ')'
          && nextChar != '('
          && nextChar != '/'
          && nextChar != ':'
          && currentChar != ')'
          && currentChar != '('
          && previousNonWSChar != '('
          && !( nextChar == '*'
                && !isCharPotentialOperator( previousNonWSChar )
                && pointerAlignment == PTR_ALIGN_TYPE )
          && !( nextChar == '&'
                && !isCharPotentialOperator( previousNonWSChar )
                && ( referenceAlignment == REF_ALIGN_TYPE
                     || ( referenceAlignment == REF_SAME_AS_PTR && pointerAlignment == PTR_ALIGN_TYPE ) ) )
        ) {
        if( formattedLine.length() - 1 <= maxCodeLength ) {
          maxWhiteSpace = formattedLine.length() - 1;
        } else
        { maxWhiteSpacePending = formattedLine.length() - 1; }
      }
    } else if( appendedChar == ')' ) {
      if( nextChar != ')'
          && nextChar != ' '
          && nextChar != ';'
          && nextChar != ','
          && nextChar != '.'
          && !( nextChar == '-' && pointerSymbolFollows() ) ) {
        if( formattedLine.length() <= maxCodeLength ) {
          maxWhiteSpace = formattedLine.length();
        } else
        { maxWhiteSpacePending = formattedLine.length(); }
      }
    } else if( appendedChar == ',' ) {
      if( formattedLine.length() <= maxCodeLength ) {
        maxComma = formattedLine.length();
      } else
      { maxCommaPending = formattedLine.length(); }
    } else if( appendedChar == '(' ) {
      if( nextChar != ')' && nextChar != '(' && nextChar != '"' && nextChar != '\'' ) {
        size_t parenNum;
        if( isCharPotentialOperator( previousNonWSChar ) ) {
          parenNum = formattedLine.length() - 1;
        } else
        { parenNum = formattedLine.length(); }
        if( formattedLine.length() <= maxCodeLength ) {
          maxParen = parenNum;
        } else
        { maxParenPending = parenNum; }
      }
    } else if( appendedChar == ';' ) {
      if( nextChar != ' '  && nextChar != '}' && nextChar != '/' ) {
        if( formattedLine.length() <= maxCodeLength ) {
          maxSemi = formattedLine.length();
        } else
        { maxSemiPending = formattedLine.length(); }
      }
    }
  }

  void ASFormatter::updateFormattedLineSplitPointsOperator( const string& sequence ) {
    assert( maxCodeLength != string::npos );
    assert( formattedLine.length() > 0 );
    if( !isOkToSplitFormattedLine() ) {
      return;
    }
    char nextChar = peekNextChar();
    if( nextChar == '/' ) {
      return;
    }
    if( sequence == "||" || sequence == "&&" || sequence == "or" || sequence == "and" ) {
      if( shouldBreakLineAfterLogical ) {
        if( formattedLine.length() <= maxCodeLength ) {
          maxAndOr = formattedLine.length();
        } else
        { maxAndOrPending = formattedLine.length(); }
      } else {
        size_t sequenceLength = sequence.length();
        if( formattedLine.length() > sequenceLength
            && isWhiteSpace( formattedLine[formattedLine.length() - sequenceLength - 1] ) ) {
          sequenceLength++;
        }
        if( formattedLine.length() - sequenceLength <= maxCodeLength ) {
          maxAndOr = formattedLine.length() - sequenceLength;
        } else
        { maxAndOrPending = formattedLine.length() - sequenceLength; }
      }
    } else if( sequence == "==" || sequence == "!=" || sequence == ">=" || sequence == "<=" ) {
      if( formattedLine.length() <= maxCodeLength ) {
        maxWhiteSpace = formattedLine.length();
      } else
      { maxWhiteSpacePending = formattedLine.length(); }
    } else if( sequence == "+" || sequence == "-" || sequence == "?" ) {
      if( charNum > 0
          && !( sequence == "+" && isInExponent() )
          && !( sequence == "-"  && isInExponent() )
          && ( isLegalNameChar( currentLine[charNum - 1] )
               || currentLine[charNum - 1] == ')'
               || currentLine[charNum - 1] == ']'
               || currentLine[charNum - 1] == '\"' ) ) {
        if( formattedLine.length() - 1 <= maxCodeLength ) {
          maxWhiteSpace = formattedLine.length() - 1;
        } else
        { maxWhiteSpacePending = formattedLine.length() - 1; }
      }
    } else if( sequence == "=" || sequence == ":" ) {
      size_t splitPoint = 0;
      if( formattedLine.length() < maxCodeLength ) {
        splitPoint = formattedLine.length();
      } else
      { splitPoint = formattedLine.length() - 1; }
      if( previousNonWSChar == ']' ) {
        if( formattedLine.length() - 1 <= maxCodeLength ) {
          maxWhiteSpace = splitPoint;
        } else
        { maxWhiteSpacePending = splitPoint; }
      } else if( charNum > 0
                 && ( isLegalNameChar( currentLine[charNum - 1] )
                      || currentLine[charNum - 1] == ')'
                      || currentLine[charNum - 1] == ']' ) ) {
        if( formattedLine.length() <= maxCodeLength ) {
          maxWhiteSpace = splitPoint;
        } else
        { maxWhiteSpacePending = splitPoint; }
      }
    }
  }


  void ASFormatter::updateFormattedLineSplitPointsPointerOrReference( size_t index ) {
    assert( maxCodeLength != string::npos );
    assert( formattedLine.length() > 0 );
    assert( index < formattedLine.length() );
    if( !isOkToSplitFormattedLine() ) {
      return;
    }
    if( index < maxWhiteSpace ) {
      return;
    }
    if( index <= maxCodeLength ) {
      maxWhiteSpace = index;
    } else
    { maxWhiteSpacePending = index; }
  }

  bool ASFormatter::isOkToSplitFormattedLine() {
    assert( maxCodeLength != string::npos );
    if( shouldKeepLineUnbroken
        || isInLineComment
        || isInComment
        || isInQuote
        || isInCase
        || isInPreprocessor
        || isInExecSQL
        || isInAsm || isInAsmOneLine || isInAsmBlock
        || isInTemplate ) {
      return false;
    }
    if( !isOkToBreakBlock( braceTypeStack->back() ) && currentChar != '{' ) {
      shouldKeepLineUnbroken = true;
      clearFormattedLineSplitPoints();
      return false;
    }
    if( isBraceType( braceTypeStack->back(), ARRAY_TYPE ) ) {
      shouldKeepLineUnbroken = true;
      if( !isBraceType( braceTypeStack->back(), ARRAY_NIS_TYPE ) ) {
        clearFormattedLineSplitPoints();
      }
      return false;
    }
    return true;
  }


  void ASFormatter::testForTimeToSplitFormattedLine() {
    if( formattedLine.length() > maxCodeLength && !isLineReady ) {
      size_t splitPoint = findFormattedLineSplitPoint();
      if( splitPoint > 0 && splitPoint < formattedLine.length() ) {
        string splitLine = formattedLine.substr( splitPoint );
        formattedLine = formattedLine.substr( 0, splitPoint );
        breakLine( true );
        formattedLine = splitLine;
        string nextWord = ASBeautifier::getNextWord( currentLine, charNum - 1 );
        if( isAppendPostBlockEmptyLineRequested
            && ( nextWord == "break" || nextWord == "continue" ) ) {
          isAppendPostBlockEmptyLineRequested = false;
          isPrependPostBlockEmptyLineRequested = true;
        } else
        { isPrependPostBlockEmptyLineRequested = false; }
        maxAndOr = ( maxAndOr > splitPoint ) ? ( maxAndOr - splitPoint ) : 0;
        maxSemi = ( maxSemi > splitPoint ) ? ( maxSemi - splitPoint ) : 0;
        maxComma = ( maxComma > splitPoint ) ? ( maxComma - splitPoint ) : 0;
        maxParen = ( maxParen > splitPoint ) ? ( maxParen - splitPoint ) : 0;
        maxWhiteSpace = ( maxWhiteSpace > splitPoint ) ? ( maxWhiteSpace - splitPoint ) : 0;
        if( maxSemiPending > 0 ) {
          maxSemi = ( maxSemiPending > splitPoint ) ? ( maxSemiPending - splitPoint ) : 0;
          maxSemiPending = 0;
        }
        if( maxAndOrPending > 0 ) {
          maxAndOr = ( maxAndOrPending > splitPoint ) ? ( maxAndOrPending - splitPoint ) : 0;
          maxAndOrPending = 0;
        }
        if( maxCommaPending > 0 ) {
          maxComma = ( maxCommaPending > splitPoint ) ? ( maxCommaPending - splitPoint ) : 0;
          maxCommaPending = 0;
        }
        if( maxParenPending > 0 ) {
          maxParen = ( maxParenPending > splitPoint ) ? ( maxParenPending - splitPoint ) : 0;
          maxParenPending = 0;
        }
        if( maxWhiteSpacePending > 0 ) {
          maxWhiteSpace = ( maxWhiteSpacePending > splitPoint ) ? ( maxWhiteSpacePending - splitPoint ) : 0;
          maxWhiteSpacePending = 0;
        }
        size_t firstText = formattedLine.find_first_not_of( " \t" );
        if( firstText == string::npos && formattedLine.length() > 0 ) {
          formattedLine.erase();
          clearFormattedLineSplitPoints();
          if( isWhiteSpace( currentChar ) )
            for( size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace( currentLine[i] ); i++ )
            { goForward( 1 ); }
        } else if( firstText > 0 ) {
          formattedLine.erase( 0, firstText );
          maxSemi = ( maxSemi > firstText ) ? ( maxSemi - firstText ) : 0;
          maxAndOr = ( maxAndOr > firstText ) ? ( maxAndOr - firstText ) : 0;
          maxComma = ( maxComma > firstText ) ? ( maxComma - firstText ) : 0;
          maxParen = ( maxParen > firstText ) ? ( maxParen - firstText ) : 0;
          maxWhiteSpace = ( maxWhiteSpace > firstText ) ? ( maxWhiteSpace - firstText ) : 0;
        }
        if( formattedLineCommentNum != string::npos ) {
          formattedLineCommentNum = formattedLine.find( "//" );
          if( formattedLineCommentNum == string::npos ) {
            formattedLineCommentNum = formattedLine.find( "/*" );
          }
        }
      }
    }
  }

  size_t ASFormatter::findFormattedLineSplitPoint() const {
    assert( maxCodeLength != string::npos );
    size_t minCodeLength = 10;
    size_t splitPoint = 0;
    splitPoint = maxSemi;
    if( maxAndOr >= minCodeLength ) {
      splitPoint = maxAndOr;
    }
    if( splitPoint < minCodeLength ) {
      splitPoint = maxWhiteSpace;
      if( maxParen > splitPoint
          || maxParen >= maxCodeLength * .7 ) {
        splitPoint = maxParen;
      }
      if( maxComma > splitPoint
          || maxComma >= maxCodeLength * .3 ) {
        splitPoint = maxComma;
      }
    }
    if( splitPoint < minCodeLength ) {
      splitPoint = string::npos;
      if( maxSemiPending > 0 && maxSemiPending < splitPoint ) {
        splitPoint = maxSemiPending;
      }
      if( maxAndOrPending > 0 && maxAndOrPending < splitPoint ) {
        splitPoint = maxAndOrPending;
      }
      if( maxCommaPending > 0 && maxCommaPending < splitPoint ) {
        splitPoint = maxCommaPending;
      }
      if( maxParenPending > 0 && maxParenPending < splitPoint ) {
        splitPoint = maxParenPending;
      }
      if( maxWhiteSpacePending > 0 && maxWhiteSpacePending < splitPoint ) {
        splitPoint = maxWhiteSpacePending;
      }
      if( splitPoint == string::npos ) {
        splitPoint = 0;
      }
    } else if( formattedLine.length() - splitPoint > maxCodeLength ) {
      size_t newCharNum;
      if( isCharPotentialHeader( currentLine, charNum ) ) {
        newCharNum = getCurrentWord( currentLine, charNum ).length() + charNum;
      } else
      { newCharNum = charNum + 2; }
      if( newCharNum + 1 > currentLine.length() ) {
        if( maxWhiteSpace > splitPoint + 3 ) {
          splitPoint = maxWhiteSpace;
        }
        if( maxParen > splitPoint ) {
          splitPoint = maxParen;
        }
      }
    }
    return splitPoint;
  }

  void ASFormatter::clearFormattedLineSplitPoints() {
    maxSemi = 0;
    maxAndOr = 0;
    maxComma = 0;
    maxParen = 0;
    maxWhiteSpace = 0;
    maxSemiPending = 0;
    maxAndOrPending = 0;
    maxCommaPending = 0;
    maxParenPending = 0;
    maxWhiteSpacePending = 0;
  }
  bool ASFormatter::pointerSymbolFollows() const {
    size_t peekNum = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( peekNum == string::npos || currentLine.compare( peekNum, 2, "->" ) != 0 ) {
      return false;
    }
    return true;
  }

  bool ASFormatter::computeChecksumIn( const string & currentLine_ ) {
    for( size_t i = 0; i < currentLine_.length(); i++ )
      if( !isWhiteSpace( currentLine_[i] ) ) {
        checksumIn += currentLine_[i];
      }
    return true;
  }

  bool ASFormatter::adjustChecksumIn( int adjustment ) {
    checksumIn += adjustment;
    return true;
  }

  size_t ASFormatter::getChecksumIn() const {
    return checksumIn;
  }

  bool ASFormatter::computeChecksumOut( const string & beautifiedLine ) {
    for( size_t i = 0; i < beautifiedLine.length(); i++ )
      if( !isWhiteSpace( beautifiedLine[i] ) ) {
        checksumOut += beautifiedLine[i];
      }
    return true;
  }

  bool ASFormatter::getIsLineReady() const {
    return isLineReady;
  }

  size_t ASFormatter::getChecksumOut() const {
    return checksumOut;
  }

  int ASFormatter::getChecksumDiff() const {
    return checksumOut - checksumIn;
  }

  int ASFormatter::getFormatterFileType() const {
    return formatterFileType;
  }

  const string* ASFormatter::getFollowingOperator() const {
    size_t nextNum = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( nextNum == string::npos ) {
      return nullptr;
    }
    if( !isLegalNameChar( currentLine[nextNum] ) ) {
      return nullptr;
    }
    while( nextNum < currentLine.length() ) {
      if( !isLegalNameChar( currentLine[nextNum] )
          && !isWhiteSpace( currentLine[nextNum] ) ) {
        break;
      }
      nextNum++;
    }
    if( nextNum >= currentLine.length()
        || !isCharPotentialOperator( currentLine[nextNum] )
        || currentLine[nextNum] == '/' ) {
      return nullptr;
    }
    const string* newOperator = ASBase::findOperator( currentLine, nextNum, operators );
    return newOperator;
  }

  bool ASFormatter::isArrayOperator() const {
    assert( currentChar == '*' || currentChar == '&' || currentChar == '^' );
    assert( isBraceType( braceTypeStack->back(), ARRAY_TYPE ) );
    size_t nextNum = currentLine.find_first_not_of( " \t", charNum + 1 );
    if( nextNum == string::npos ) {
      return false;
    }
    if( !isLegalNameChar( currentLine[nextNum] ) ) {
      return false;
    }
    while( nextNum < currentLine.length() ) {
      if( !isLegalNameChar( currentLine[nextNum] )
          && !isWhiteSpace( currentLine[nextNum] ) ) {
        break;
      }
      nextNum++;
    }
    if( currentLine[nextNum] == ','
        || currentLine[nextNum] == '}'
        || currentLine[nextNum] == ')'
        || currentLine[nextNum] == '(' ) {
      return true;
    }
    return false;
  }

  void ASFormatter::resetEndOfStatement() {
    foundQuestionMark = false;
    foundNamespaceHeader = false;
    foundClassHeader = false;
    foundStructHeader = false;
    foundInterfaceHeader = false;
    foundPreDefinitionHeader = false;
    foundPreCommandHeader = false;
    foundPreCommandMacro = false;
    foundTrailingReturnType = false;
    foundCastOperator = false;
    isInPotentialCalculation = false;
    isSharpAccessor = false;
    isSharpDelegate = false;
    isInObjCMethodDefinition = false;
    isInObjCInterface = false;
    isInObjCSelector = false;
    isInEnum = false;
    isInExternC = false;
    elseHeaderFollowsComments = false;
    nonInStatementBrace = 0;
    while( !questionMarkStack->empty() ) {
      questionMarkStack->pop_back();
    }
  }

  int ASFormatter::findObjCColonAlignment() const {
    assert( currentChar == '+' || currentChar == '-' || currentChar == '[' );
    assert( getAlignMethodColon() );
    bool isFirstLine = true;
    bool haveFirstColon = false;
    bool foundMethodColon = false;
    bool isInComment_ = false;
    bool isInQuote_ = false;
    char quoteChar_ = ' ';
    int  sqBracketCount = 0;
    int  colonAdjust = 0;
    int  colonAlign = 0;
    string nextLine_ = currentLine;
    ASPeekStream stream( sourceIterator );
    while( sourceIterator->hasMoreLines() || isFirstLine ) {
      if( !isFirstLine ) {
        nextLine_ = stream.peekNextLine();
      }
      haveFirstColon = false;
      nextLine_ = ASBeautifier::trim( nextLine_ );
      for( size_t i = 0; i < nextLine_.length(); i++ ) {
        if( isWhiteSpace( nextLine_[i] ) ) {
          continue;
        }
        if( nextLine_.compare( i, 2, "/*" ) == 0 ) {
          isInComment_ = true;
        }
        if( isInComment_ ) {
          if( nextLine_.compare( i, 2, "*/" ) == 0 ) {
            isInComment_ = false;
            ++i;
          }
          continue;
        }
        if( nextLine_[i] == '\\' ) {
          ++i;
          continue;
        }
        if( isInQuote_ ) {
          if( nextLine_[i] == quoteChar_ ) {
            isInQuote_ = false;
          }
          continue;
        }
        if( nextLine_[i] == '"'
            || ( nextLine_[i] == '\'' && !isDigitSeparator( nextLine_, i ) ) ) {
          isInQuote_ = true;
          quoteChar_ = nextLine_[i];
          continue;
        }
        if( nextLine_.compare( i, 2, "//" ) == 0 ) {
          i = nextLine_.length();
          continue;
        }
        if( ( nextLine_[i] == '{' && ( currentChar == '-' || currentChar == '+' ) )
            || nextLine_[i] == ';' ) {
          goto EndOfWhileLoop;
        }
        if( nextLine_[i] == ']' ) {
          --sqBracketCount;
          if( sqBracketCount == 0 ) {
            goto EndOfWhileLoop;
          }
        }
        if( nextLine_[i] == '[' ) {
          ++sqBracketCount;
        }
        if( isFirstLine ) {
          continue;
        }
        if( sqBracketCount > 1 ) {
          continue;
        }
        if( haveFirstColon ) {
          continue;
        }
        if( nextLine_[i] == ':' ) {
          haveFirstColon = true;
          foundMethodColon = true;
          if( shouldPadMethodColon ) {
            int spacesStart;
            for( spacesStart = i; spacesStart > 0; spacesStart-- )
              if( !isWhiteSpace( nextLine_[spacesStart - 1] ) )
              { break; }
            int spaces = i - spacesStart;
            if( objCColonPadMode == COLON_PAD_ALL || objCColonPadMode == COLON_PAD_BEFORE )
            { colonAdjust = 1 - spaces; }
            else if( objCColonPadMode == COLON_PAD_NONE || objCColonPadMode == COLON_PAD_AFTER )
            { colonAdjust = 0 - spaces; }
          }
          int colonPosition = i + colonAdjust;
          if( colonPosition > colonAlign ) {
            colonAlign = colonPosition;
          }
        }
      }
      isFirstLine = false;
    }
  EndOfWhileLoop:
    if( !foundMethodColon ) {
      colonAlign = -1;
    }
    return colonAlign;
  }

  void ASFormatter::padObjCMethodColon() {
    assert( currentChar == ':' );
    int commentAdjust = 0;
    char nextChar = peekNextChar();
    if( objCColonPadMode == COLON_PAD_NONE
        || objCColonPadMode == COLON_PAD_AFTER
        || nextChar == ')' ) {
      for( int i = formattedLine.length() - 1; ( i > -1 ) && isWhiteSpace( formattedLine[i] ); i-- ) {
        formattedLine.erase( i );
        --commentAdjust;
      }
    } else {
      for( int i = formattedLine.length() - 1; ( i > 0 ) && isWhiteSpace( formattedLine[i] ); i-- )
        if( isWhiteSpace( formattedLine[i - 1] ) ) {
          formattedLine.erase( i );
          --commentAdjust;
        }
      appendSpacePad();
    }
    if( objCColonPadMode == COLON_PAD_NONE
        || objCColonPadMode == COLON_PAD_BEFORE
        || nextChar == ')' ) {
      int nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
      if( nextText == ( int )string::npos ) {
        nextText = currentLine.length();
      }
      int spaces = nextText - charNum - 1;
      if( spaces > 0 ) {
        currentLine.erase( charNum + 1, spaces );
        spacePadNum -= spaces;
      }
    } else {
      int nextText = currentLine.find_first_not_of( " \t", charNum + 1 );
      if( nextText == ( int )string::npos ) {
        nextText = currentLine.length();
      }
      int spaces = nextText - charNum - 1;
      if( spaces == 0 ) {
        currentLine.insert( charNum + 1, 1, ' ' );
        spacePadNum += 1;
      } else if( spaces > 1 ) {
        currentLine.erase( charNum + 1, spaces - 1 );
        spacePadNum -= spaces - 1;
      }
    }
    spacePadNum += commentAdjust;
  }

  void ASFormatter::stripCommentPrefix() {
    int firstChar = formattedLine.find_first_not_of( " \t" );
    if( firstChar < 0 ) {
      return;
    }
    if( isInCommentStartLine ) {
      if( formattedLine.compare( firstChar, 2, "/*" ) != 0 ) {
        return;
      }
      int commentOpener = firstChar;
      int commentEnd = formattedLine.find( "*/", firstChar + 2 );
      if( commentEnd != -1 ) {
        return;
      }
      int followingText = formattedLine.find_first_not_of( " \t", commentOpener + 2 );
      if( followingText < 0 ) {
        return;
      }
      if( formattedLine[followingText] == '*' || formattedLine[followingText] == '!' ) {
        followingText = formattedLine.find_first_not_of( " \t", followingText + 1 );
      }
      if( followingText < 0 ) {
        return;
      }
      if( formattedLine[followingText] == '*' ) {
        return;
      }
      int indentLen = getIndentLength();
      int followingTextIndent = followingText - commentOpener;
      if( followingTextIndent < indentLen ) {
        string stringToInsert( indentLen - followingTextIndent, ' ' );
        formattedLine.insert( followingText, stringToInsert );
      }
      return;
    }
    if( formattedLine[firstChar] == '*' ) {
      if( formattedLine.compare( firstChar, 2, "*/" ) == 0 ) {
        formattedLine = "*/";
      } else {
        int secondChar = formattedLine.find_first_not_of( " \t", firstChar + 1 );
        if( secondChar < 0 ) {
          adjustChecksumIn( -'*' );
          formattedLine.erase();
          return;
        }
        if( formattedLine[secondChar] == '*' ) {
          return;
        }
        int indentLen = getIndentLength();
        adjustChecksumIn( -'*' );
        if( formattedLine.substr( 0, secondChar ).find( '\t' ) != string::npos ) {
          formattedLine.erase( firstChar, 1 );
        } else {
          int spacesToInsert = 0;
          if( secondChar >= indentLen ) {
            spacesToInsert = secondChar;
          } else
          { spacesToInsert = indentLen; }
          formattedLine = string( spacesToInsert, ' ' ) + formattedLine.substr( secondChar );
        }
        int lastChar = formattedLine.find_last_not_of( " \t" );
        if( lastChar > -1 && formattedLine[lastChar] == '*' ) {
          adjustChecksumIn( -'*' );
          formattedLine[lastChar] = ' ';
        }
      }
    } else {
      if( formattedLine.substr( 0, firstChar ).find( '\t' ) == string::npos ) {
        int indentLen = getIndentLength();
        if( firstChar < indentLen ) {
          string stringToInsert( indentLen, ' ' );
          formattedLine = stringToInsert + formattedLine.substr( firstChar );
        }
      }
    }
  }
}
